6272
6311
DBUG_RETURN(m_file[0]->keys_to_use_for_scanning());
6275
#define MAX_PARTS_FOR_OPTIMIZER_CALLS 10
6277
Prepare start variables for estimating optimizer costs.
6279
@param[out] num_used_parts Number of partitions after pruning.
6280
@param[out] check_min_num Number of partitions to call.
6281
@param[out] first first used partition.
6283
void ha_partition::partitions_optimizer_call_preparations(uint *first,
6284
uint *num_used_parts,
6285
uint *check_min_num)
6287
*first= bitmap_get_first_set(&(m_part_info->used_partitions));
6288
*num_used_parts= bitmap_bits_set(&(m_part_info->used_partitions));
6289
*check_min_num= min(MAX_PARTS_FOR_OPTIMIZER_CALLS, *num_used_parts);
6316
Minimum number of rows to base optimizer estimate on.
6319
ha_rows ha_partition::min_rows_for_estimate()
6321
uint i, max_used_partitions, tot_used_partitions;
6322
DBUG_ENTER("ha_partition::min_rows_for_estimate");
6324
tot_used_partitions= bitmap_bits_set(&m_part_info->used_partitions);
6325
DBUG_ASSERT(tot_used_partitions);
6328
Allow O(log2(tot_partitions)) increase in number of used partitions.
6329
This gives O(tot_rows/log2(tot_partitions)) rows to base the estimate on.
6330
I.e when the total number of partitions doubles, allow one more
6331
partition to be checked.
6334
max_used_partitions= 1;
6335
while (i < m_tot_parts)
6337
max_used_partitions++;
6340
if (max_used_partitions > tot_used_partitions)
6341
max_used_partitions= tot_used_partitions;
6343
/* stats.records is already updated by the info(HA_STATUS_VARIABLE) call. */
6344
DBUG_PRINT("info", ("max_used_partitions: %u tot_rows: %lu",
6345
max_used_partitions,
6346
(ulong) stats.records));
6347
DBUG_PRINT("info", ("tot_used_partitions: %u min_rows_to_check: %lu",
6348
tot_used_partitions,
6349
(ulong) stats.records * max_used_partitions
6350
/ tot_used_partitions));
6351
DBUG_RETURN(stats.records * max_used_partitions / tot_used_partitions);
6356
Get the biggest used partition.
6358
Starting at the N:th biggest partition and skips all non used
6359
partitions, returning the biggest used partition found
6361
@param[in,out] part_index Skip the *part_index biggest partitions
6363
@return The biggest used partition with index not lower than *part_index.
6364
@retval NO_CURRENT_PART_ID No more partition used.
6365
@retval != NO_CURRENT_PART_ID partition id of biggest used partition with
6366
index >= *part_index supplied. Note that
6367
*part_index will be updated to the next
6368
partition index to use.
6371
uint ha_partition::get_biggest_used_partition(uint *part_index)
6374
while ((*part_index) < m_tot_parts)
6376
part_id= m_part_ids_sorted_by_num_of_records[(*part_index)++];
6377
if (bitmap_is_set(&m_part_info->used_partitions, part_id))
6380
return NO_CURRENT_PART_ID;
6303
6394
double ha_partition::scan_time()
6305
double scan_time= 0.0;
6306
uint first, part_id, num_used_parts, check_min_num, partitions_called= 0;
6396
double scan_time= 0;
6307
6398
DBUG_ENTER("ha_partition::scan_time");
6309
partitions_optimizer_call_preparations(&first, &num_used_parts, &check_min_num);
6310
for (part_id= first; partitions_called < num_used_parts ; part_id++)
6312
if (!bitmap_is_set(&(m_part_info->used_partitions), part_id))
6314
scan_time+= m_file[part_id]->scan_time();
6315
partitions_called++;
6316
if (partitions_called >= check_min_num && scan_time != 0.0)
6318
DBUG_RETURN(scan_time *
6319
(double) num_used_parts / (double) partitions_called);
6400
for (file= m_file; *file; file++)
6401
if (bitmap_is_set(&(m_part_info->used_partitions), (file - m_file)))
6402
scan_time+= (*file)->scan_time();
6322
6403
DBUG_RETURN(scan_time);
6327
Estimate rows for records_in_range or estimate_rows_upper_bound.
6329
@param is_records_in_range call records_in_range instead of
6330
estimate_rows_upper_bound.
6331
@param inx (only for records_in_range) index to use.
6332
@param min_key (only for records_in_range) start of range.
6333
@param max_key (only for records_in_range) end of range.
6335
@return Number of rows or HA_POS_ERROR.
6408
Find number of records in a range.
6409
@param inx Index number
6410
@param min_key Start of range
6411
@param max_key End of range
6413
@return Number of rows in range.
6415
Given a starting key, and an ending key estimate the number of rows that
6416
will exist between the two. max_key may be empty which in case determine
6417
if start_key matches any rows.
6337
ha_rows ha_partition::estimate_rows(bool is_records_in_range, uint inx,
6338
key_range *min_key, key_range *max_key)
6420
ha_rows ha_partition::records_in_range(uint inx, key_range *min_key,
6340
ha_rows rows, estimated_rows= 0;
6341
uint first, part_id, num_used_parts, check_min_num, partitions_called= 0;
6423
ha_rows min_rows_to_check, rows, estimated_rows=0, checked_rows= 0;
6424
uint partition_index= 0, part_id;
6342
6425
DBUG_ENTER("ha_partition::records_in_range");
6344
partitions_optimizer_call_preparations(&first, &num_used_parts, &check_min_num);
6345
for (part_id= first; partitions_called < num_used_parts ; part_id++)
6427
min_rows_to_check= min_rows_for_estimate();
6429
while ((part_id= get_biggest_used_partition(&partition_index))
6430
!= NO_CURRENT_PART_ID)
6347
if (!bitmap_is_set(&(m_part_info->used_partitions), part_id))
6349
if (is_records_in_range)
6350
rows= m_file[part_id]->records_in_range(inx, min_key, max_key);
6352
rows= m_file[part_id]->estimate_rows_upper_bound();
6432
rows= m_file[part_id]->records_in_range(inx, min_key, max_key);
6434
DBUG_PRINT("info", ("part %u match %lu rows of %lu", part_id, (ulong) rows,
6435
(ulong) m_file[part_id]->stats.records));
6353
6437
if (rows == HA_POS_ERROR)
6354
6438
DBUG_RETURN(HA_POS_ERROR);
6355
6439
estimated_rows+= rows;
6356
partitions_called++;
6357
if (partitions_called >= check_min_num && estimated_rows)
6440
checked_rows+= m_file[part_id]->stats.records;
6442
Returning 0 means no rows can be found, so we must continue
6443
this loop as long as we have estimated_rows == 0.
6444
Also many engines return 1 to indicate that there may exist
6445
a matching row, we do not normalize this by dividing by number of
6446
used partitions, but leave it to be returned as a sum, which will
6447
reflect that we will need to scan each partition's index.
6449
Note that this statistics may not always be correct, so we must
6450
continue even if the current partition has 0 rows, since we might have
6451
deleted rows from the current partition, or inserted to the next
6454
if (estimated_rows && checked_rows &&
6455
checked_rows >= min_rows_to_check)
6359
DBUG_RETURN(estimated_rows * num_used_parts / partitions_called);
6458
("records_in_range(inx %u): %lu (%lu * %lu / %lu)",
6460
(ulong) (estimated_rows * stats.records / checked_rows),
6461
(ulong) estimated_rows,
6462
(ulong) stats.records,
6463
(ulong) checked_rows));
6464
DBUG_RETURN(estimated_rows * stats.records / checked_rows);
6467
DBUG_PRINT("info", ("records_in_range(inx %u): %lu",
6469
(ulong) estimated_rows));
6362
6470
DBUG_RETURN(estimated_rows);
6367
Find number of records in a range
6372
min_key Start of range
6373
max_key End of range
6376
Number of rows in range
6379
Given a starting key, and an ending key estimate the number of rows that
6380
will exist between the two. end_key may be empty which in case determine
6381
if start_key matches any rows.
6383
Called from opt_range.cc by check_quick_keys().
6385
monty: MUST be called for each range and added.
6386
Note that MySQL will assume that if this returns 0 there is no
6387
matching rows for the range!
6390
ha_rows ha_partition::records_in_range(uint inx, key_range *min_key,
6393
DBUG_ENTER("ha_partition::records_in_range");
6395
DBUG_RETURN(estimate_rows(TRUE, inx, min_key, max_key));
6400
Estimate upper bound of number of rows
6403
estimate_rows_upper_bound()
6475
Estimate upper bound of number of rows.
6477
@return Number of rows.
6409
6480
ha_rows ha_partition::estimate_rows_upper_bound()
6482
ha_rows rows, tot_rows= 0;
6483
handler **file= m_file;
6411
6484
DBUG_ENTER("ha_partition::estimate_rows_upper_bound");
6413
DBUG_RETURN(estimate_rows(FALSE, 0, NULL, NULL));
6488
if (bitmap_is_set(&(m_part_info->used_partitions), (file - m_file)))
6490
rows= (*file)->estimate_rows_upper_bound();
6491
if (rows == HA_POS_ERROR)
6492
DBUG_RETURN(HA_POS_ERROR);
6495
} while (*(++file));
6496
DBUG_RETURN(tot_rows);