~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/optimizer/range.cc

Merge Padraig

Show diffs side-by-side

added added

removed removed

Lines of Context:
313
313
                                  uint32_t *bufsize,
314
314
                                  COST_VECT *cost);
315
315
 
316
 
static optimizer::TRP_RANGE *get_key_scans_params(optimizer::Parameter *param,
317
 
                                                  SEL_TREE *tree,
318
 
                                                  bool index_read_must_be_used,
319
 
                                                  bool update_tbl_stats,
 
316
static optimizer::RangeReadPlan *get_key_scans_params(optimizer::Parameter *param,
 
317
                                                      SEL_TREE *tree,
 
318
                                                      bool index_read_must_be_used,
 
319
                                                      bool update_tbl_stats,
 
320
                                                      double read_time);
 
321
 
 
322
static
 
323
optimizer::RorIntersectReadPlan *get_best_ror_intersect(const optimizer::Parameter *param,
 
324
                                                        SEL_TREE *tree,
 
325
                                                        double read_time,
 
326
                                                        bool *are_all_covering);
 
327
 
 
328
static
 
329
optimizer::RorIntersectReadPlan *get_best_covering_ror_intersect(optimizer::Parameter *param,
 
330
                                                                 SEL_TREE *tree,
 
331
                                                                 double read_time);
 
332
 
 
333
static
 
334
optimizer::TableReadPlan *get_best_disjunct_quick(optimizer::Parameter *param,
 
335
                                                  SEL_IMERGE *imerge,
320
336
                                                  double read_time);
321
337
 
322
338
static
323
 
optimizer::TRP_ROR_INTERSECT *get_best_ror_intersect(const optimizer::Parameter *param,
324
 
                                                     SEL_TREE *tree,
325
 
                                                     double read_time,
326
 
                                                     bool *are_all_covering);
327
 
 
328
 
static
329
 
optimizer::TRP_ROR_INTERSECT *get_best_covering_ror_intersect(optimizer::Parameter *param,
330
 
                                                              SEL_TREE *tree,
331
 
                                                              double read_time);
332
 
 
333
 
static
334
 
optimizer::TABLE_READ_PLAN *get_best_disjunct_quick(optimizer::Parameter *param,
335
 
                                                    SEL_IMERGE *imerge,
336
 
                                                    double read_time);
337
 
 
338
 
static
339
 
optimizer::TRP_GROUP_MIN_MAX *get_best_group_min_max(optimizer::Parameter *param, SEL_TREE *tree);
 
339
optimizer::GroupMinMaxReadPlan *get_best_group_min_max(optimizer::Parameter *param, SEL_TREE *tree);
340
340
 
341
341
static void print_sel_tree(optimizer::Parameter *param,
342
342
                           SEL_TREE *tree,
1004
1004
        read_time= key_read_time;
1005
1005
    }
1006
1006
 
1007
 
    optimizer::TABLE_READ_PLAN *best_trp= NULL;
1008
 
    optimizer::TRP_GROUP_MIN_MAX *group_trp= NULL;
 
1007
    optimizer::TableReadPlan *best_trp= NULL;
 
1008
    optimizer::GroupMinMaxReadPlan *group_trp= NULL;
1009
1009
    double best_read_time= read_time;
1010
1010
 
1011
1011
    if (cond)
1051
1051
      */
1052
1052
      if (tree->merges.is_empty())
1053
1053
      {
1054
 
        optimizer::TRP_RANGE *range_trp= NULL;
1055
 
        optimizer::TRP_ROR_INTERSECT *rori_trp= NULL;
 
1054
        optimizer::RangeReadPlan *range_trp= NULL;
 
1055
        optimizer::RorIntersectReadPlan *rori_trp= NULL;
1056
1056
        bool can_build_covering= false;
1057
1057
 
1058
1058
        /* Get best 'range' plan and prepare data for making other plans */
1093
1093
      else
1094
1094
      {
1095
1095
        /* Try creating index_merge/ROR-union scan. */
1096
 
        SEL_IMERGE *imerge;
1097
 
        optimizer::TABLE_READ_PLAN *best_conj_trp= NULL;
1098
 
        optimizer::TABLE_READ_PLAN *new_conj_trp= NULL;
 
1096
        SEL_IMERGE *imerge= NULL;
 
1097
        optimizer::TableReadPlan *best_conj_trp= NULL;
 
1098
        optimizer::TableReadPlan *new_conj_trp= NULL;
1099
1099
        List_iterator_fast<SEL_IMERGE> it(tree->merges);
1100
1100
        while ((imerge= it++))
1101
1101
        {
1204
1204
*/
1205
1205
 
1206
1206
static
1207
 
optimizer::TABLE_READ_PLAN *get_best_disjunct_quick(optimizer::Parameter *param,
1208
 
                                                    SEL_IMERGE *imerge,
1209
 
                                                    double read_time)
 
1207
optimizer::TableReadPlan *get_best_disjunct_quick(optimizer::Parameter *param,
 
1208
                                                  SEL_IMERGE *imerge,
 
1209
                                                  double read_time)
1210
1210
{
1211
1211
  SEL_TREE **ptree;
1212
 
  optimizer::TRP_INDEX_MERGE *imerge_trp= NULL;
 
1212
  optimizer::IndexMergeReadPlan *imerge_trp= NULL;
1213
1213
  uint32_t n_child_scans= imerge->trees_next - imerge->trees;
1214
 
  optimizer::TRP_RANGE **range_scans= NULL;
1215
 
  optimizer::TRP_RANGE **cur_child= NULL;
1216
 
  optimizer::TRP_RANGE **cpk_scan= NULL;
 
1214
  optimizer::RangeReadPlan **range_scans= NULL;
 
1215
  optimizer::RangeReadPlan **cur_child= NULL;
 
1216
  optimizer::RangeReadPlan **cpk_scan= NULL;
1217
1217
  bool imerge_too_expensive= false;
1218
1218
  double imerge_cost= 0.0;
1219
1219
  ha_rows cpk_scan_records= 0;
1222
1222
  bool all_scans_ror_able= true;
1223
1223
  bool all_scans_rors= true;
1224
1224
  uint32_t unique_calc_buff_size;
1225
 
  optimizer::TABLE_READ_PLAN **roru_read_plans= NULL;
1226
 
  optimizer::TABLE_READ_PLAN **cur_roru_plan= NULL;
 
1225
  optimizer::TableReadPlan **roru_read_plans= NULL;
 
1226
  optimizer::TableReadPlan **cur_roru_plan= NULL;
1227
1227
  double roru_index_costs;
1228
1228
  ha_rows roru_total_records;
1229
1229
  double roru_intersect_part= 1.0;
1230
1230
 
1231
 
  if (!(range_scans= (optimizer::TRP_RANGE**)alloc_root(param->mem_root,
1232
 
                                                        sizeof(optimizer::TRP_RANGE*)*
1233
 
                                                        n_child_scans)))
 
1231
  if (! (range_scans= (optimizer::RangeReadPlan**)alloc_root(param->mem_root,
 
1232
                                                             sizeof(optimizer::RangeReadPlan*)*
 
1233
                                                             n_child_scans)))
1234
1234
    return NULL;
1235
1235
  /*
1236
1236
    Collect best 'range' scan for each of disjuncts, and, while doing so,
1280
1280
  }
1281
1281
  if (all_scans_rors)
1282
1282
  {
1283
 
    roru_read_plans= (optimizer::TABLE_READ_PLAN**)range_scans;
 
1283
    roru_read_plans= (optimizer::TableReadPlan **) range_scans;
1284
1284
    goto skip_to_ror_scan;
1285
1285
  }
1286
1286
  if (cpk_scan)
1323
1323
                         param->session->variables.sortbuff_size);
1324
1324
  if (imerge_cost < read_time)
1325
1325
  {
1326
 
    if ((imerge_trp= new (param->mem_root) optimizer::TRP_INDEX_MERGE))
 
1326
    if ((imerge_trp= new (param->mem_root) optimizer::IndexMergeReadPlan))
1327
1327
    {
1328
1328
      imerge_trp->read_cost= imerge_cost;
1329
1329
      imerge_trp->records= non_cpk_scan_records + cpk_scan_records;
1341
1341
 
1342
1342
  /* Ok, it is possible to build a ROR-union, try it. */
1343
1343
  bool dummy;
1344
 
  if (!(roru_read_plans=
1345
 
          (optimizer::TABLE_READ_PLAN**)alloc_root(param->mem_root,
1346
 
                                                   sizeof(optimizer::TABLE_READ_PLAN*)*
 
1344
  if (! (roru_read_plans=
 
1345
          (optimizer::TableReadPlan **) alloc_root(param->mem_root,
 
1346
                                                   sizeof(optimizer::TableReadPlan*)*
1347
1347
                                                   n_child_scans)))
1348
 
    return(imerge_trp);
 
1348
    return imerge_trp;
1349
1349
skip_to_ror_scan:
1350
1350
  roru_index_costs= 0.0;
1351
1351
  roru_total_records= 0;
1374
1374
    else
1375
1375
      cost= read_time;
1376
1376
 
1377
 
    optimizer::TABLE_READ_PLAN *prev_plan= *cur_child;
 
1377
    optimizer::TableReadPlan *prev_plan= *cur_child;
1378
1378
    if (!(*cur_roru_plan= get_best_ror_intersect(param, *ptree, cost,
1379
1379
                                                 &dummy)))
1380
1380
    {
1386
1386
    }
1387
1387
    else
1388
1388
      roru_index_costs +=
1389
 
        ((optimizer::TRP_ROR_INTERSECT*)(*cur_roru_plan))->index_scan_costs;
 
1389
        ((optimizer::RorIntersectReadPlan*)(*cur_roru_plan))->index_scan_costs;
1390
1390
    roru_total_records += (*cur_roru_plan)->records;
1391
1391
    roru_intersect_part *= (*cur_roru_plan)->records /
1392
1392
                           param->table->cursor->stats.records;
1421
1421
                     sweep_cost.total_cost();
1422
1422
  }
1423
1423
 
1424
 
  optimizer::TRP_ROR_UNION *roru= NULL;
 
1424
  optimizer::RorUnionReadPlan *roru= NULL;
1425
1425
  if (roru_total_cost < read_time)
1426
1426
  {
1427
 
    if ((roru= new (param->mem_root) optimizer::TRP_ROR_UNION))
 
1427
    if ((roru= new (param->mem_root) optimizer::RorUnionReadPlan))
1428
1428
    {
1429
1429
      roru->first_ror= roru_read_plans;
1430
1430
      roru->last_ror= roru_read_plans + n_child_scans;
1954
1954
*/
1955
1955
 
1956
1956
static
1957
 
optimizer::TRP_ROR_INTERSECT *get_best_ror_intersect(const optimizer::Parameter *param,
1958
 
                                                     SEL_TREE *tree,
1959
 
                                                     double read_time,
1960
 
                                                     bool *are_all_covering)
 
1957
optimizer::RorIntersectReadPlan *get_best_ror_intersect(const optimizer::Parameter *param,
 
1958
                                                   SEL_TREE *tree,
 
1959
                                                   double read_time,
 
1960
                                                   bool *are_all_covering)
1961
1961
{
1962
1962
  uint32_t idx;
1963
1963
  double min_cost= DBL_MAX;
2080
2080
  }
2081
2081
 
2082
2082
  /* Ok, return ROR-intersect plan if we have found one */
2083
 
  optimizer::TRP_ROR_INTERSECT *trp= NULL;
 
2083
  optimizer::RorIntersectReadPlan *trp= NULL;
2084
2084
  if (min_cost < read_time && (cpk_scan_used || best_num > 1))
2085
2085
  {
2086
 
    if (! (trp= new (param->mem_root) optimizer::TRP_ROR_INTERSECT))
 
2086
    if (! (trp= new (param->mem_root) optimizer::RorIntersectReadPlan))
2087
2087
      return trp;
2088
2088
 
2089
2089
    if (! (trp->first_scan=
2141
2141
*/
2142
2142
 
2143
2143
static
2144
 
optimizer::TRP_ROR_INTERSECT *get_best_covering_ror_intersect(optimizer::Parameter *param,
2145
 
                                                              SEL_TREE *tree,
2146
 
                                                              double read_time)
 
2144
optimizer::RorIntersectReadPlan *get_best_covering_ror_intersect(optimizer::Parameter *param,
 
2145
                                                            SEL_TREE *tree,
 
2146
                                                            double read_time)
2147
2147
{
2148
2148
  ROR_SCAN_INFO **ror_scan_mark;
2149
2149
  ROR_SCAN_INFO **ror_scans_end= tree->ror_scans_end;
2233
2233
  if (total_cost > read_time)
2234
2234
    return NULL;
2235
2235
 
2236
 
  optimizer::TRP_ROR_INTERSECT *trp= NULL;
2237
 
  if (! (trp= new (param->mem_root) optimizer::TRP_ROR_INTERSECT))
 
2236
  optimizer::RorIntersectReadPlan *trp= NULL;
 
2237
  if (! (trp= new (param->mem_root) optimizer::RorIntersectReadPlan))
2238
2238
  {
2239
2239
    return trp;
2240
2240
  }
2282
2282
    NULL if no plan found or error occurred
2283
2283
*/
2284
2284
 
2285
 
static optimizer::TRP_RANGE *get_key_scans_params(optimizer::Parameter *param,
2286
 
                                                  SEL_TREE *tree,
2287
 
                                                  bool index_read_must_be_used,
2288
 
                                                  bool update_tbl_stats,
2289
 
                                                  double read_time)
 
2285
static optimizer::RangeReadPlan *get_key_scans_params(optimizer::Parameter *param,
 
2286
                                                      SEL_TREE *tree,
 
2287
                                                      bool index_read_must_be_used,
 
2288
                                                      bool update_tbl_stats,
 
2289
                                                      double read_time)
2290
2290
{
2291
2291
  uint32_t idx;
2292
2292
  optimizer::SEL_ARG **key= NULL;
2295
2295
  ha_rows best_records= 0;
2296
2296
  uint32_t best_mrr_flags= 0;
2297
2297
  uint32_t best_buf_size= 0;
2298
 
  optimizer::TRP_RANGE *read_plan= NULL;
 
2298
  optimizer::RangeReadPlan *read_plan= NULL;
2299
2299
  /*
2300
2300
    Note that there may be trees that have type SEL_TREE::KEY but contain no
2301
2301
    key reads at all, e.g. tree for expression "key1 is not null" where key1
2344
2344
  if (key_to_read)
2345
2345
  {
2346
2346
    idx= key_to_read - tree->keys;
2347
 
    if ((read_plan= new (param->mem_root) optimizer::TRP_RANGE(*key_to_read, idx,
2348
 
                                                               best_mrr_flags)))
 
2347
    if ((read_plan= new (param->mem_root) optimizer::RangeReadPlan(*key_to_read, idx,
 
2348
                                                                   best_mrr_flags)))
2349
2349
    {
2350
2350
      read_plan->records= best_records;
2351
2351
      read_plan->is_ror= tree->ror_scans_map.test(idx);
2358
2358
}
2359
2359
 
2360
2360
 
2361
 
optimizer::QuickSelectInterface *optimizer::TRP_INDEX_MERGE::make_quick(optimizer::Parameter *param, bool, memory::Root *)
 
2361
optimizer::QuickSelectInterface *optimizer::IndexMergeReadPlan::make_quick(optimizer::Parameter *param, bool, memory::Root *)
2362
2362
{
2363
2363
  optimizer::QuickIndexMergeSelect *quick_imerge;
2364
2364
  optimizer::QuickRangeSelect *quick= NULL;
2370
2370
 
2371
2371
  quick_imerge->records= records;
2372
2372
  quick_imerge->read_time= read_cost;
2373
 
  for (optimizer::TRP_RANGE **range_scan= range_scans; 
 
2373
  for (optimizer::RangeReadPlan **range_scan= range_scans; 
2374
2374
       range_scan != range_scans_end;
2375
2375
       range_scan++)
2376
2376
  {
2386
2386
  return quick_imerge;
2387
2387
}
2388
2388
 
2389
 
optimizer::QuickSelectInterface *optimizer::TRP_ROR_INTERSECT::make_quick(optimizer::Parameter *param,
2390
 
                                                                          bool retrieve_full_rows,
2391
 
                                                                          memory::Root *parent_alloc)
 
2389
optimizer::QuickSelectInterface *optimizer::RorIntersectReadPlan::make_quick(optimizer::Parameter *param,
 
2390
                                                                             bool retrieve_full_rows,
 
2391
                                                                             memory::Root *parent_alloc)
2392
2392
{
2393
2393
  optimizer::QuickRorIntersectSelect *quick_intersect= NULL;
2394
2394
  optimizer::QuickRangeSelect *quick= NULL;
2441
2441
}
2442
2442
 
2443
2443
 
2444
 
optimizer::QuickSelectInterface *optimizer::TRP_ROR_UNION::make_quick(optimizer::Parameter *param, bool, memory::Root *)
 
2444
optimizer::QuickSelectInterface *optimizer::RorUnionReadPlan::make_quick(optimizer::Parameter *param, bool, memory::Root *)
2445
2445
{
2446
2446
  optimizer::QuickRorUnionSelect *quick_roru= NULL;
2447
 
  optimizer::TABLE_READ_PLAN **scan= NULL;
 
2447
  optimizer::TableReadPlan **scan= NULL;
2448
2448
  optimizer::QuickSelectInterface *quick= NULL;
2449
2449
  /*
2450
2450
    It is impossible to construct a ROR-union that will not retrieve full
5350
5350
 
5351
5351
  RETURN
5352
5352
    If mem_root != NULL
5353
 
    - valid TRP_GROUP_MIN_MAX object if this QUICK class can be used for
 
5353
    - valid GroupMinMaxReadPlan object if this QUICK class can be used for
5354
5354
      the query
5355
5355
    -  NULL o/w.
5356
5356
    If mem_root == NULL
5357
5357
    - NULL
5358
5358
*/
5359
 
static optimizer::TRP_GROUP_MIN_MAX *
 
5359
static optimizer::GroupMinMaxReadPlan *
5360
5360
get_best_group_min_max(optimizer::Parameter *param, SEL_TREE *tree)
5361
5361
{
5362
5362
  Session *session= param->session;
5373
5373
  uint32_t used_key_parts= 0;   /* Number of index key parts used for access. */
5374
5374
  unsigned char key_infix[MAX_KEY_LENGTH]; /* Constants from equality predicates.*/
5375
5375
  uint32_t key_infix_len= 0;          /* Length of key_infix. */
5376
 
  optimizer::TRP_GROUP_MIN_MAX *read_plan= NULL; /* The eventually constructed TRP. */
 
5376
  optimizer::GroupMinMaxReadPlan *read_plan= NULL; /* The eventually constructed TRP. */
5377
5377
  uint32_t key_part_nr;
5378
5378
  order_st *tmp_group= NULL;
5379
5379
  Item *item= NULL;
5772
5772
 
5773
5773
  /* The query passes all tests, so construct a new TRP object. */
5774
5774
  read_plan=
5775
 
    new(param->mem_root) optimizer::TRP_GROUP_MIN_MAX(have_min,
5776
 
                                                      have_max,
5777
 
                                                      min_max_arg_part,
5778
 
                                                      group_prefix_len,
5779
 
                                                      used_key_parts,
5780
 
                                                      group_key_parts,
5781
 
                                                      index_info,
5782
 
                                                      index,
5783
 
                                                      key_infix_len,
5784
 
                                                      (key_infix_len > 0) ? key_infix : NULL,
5785
 
                                                      tree,
5786
 
                                                      best_index_tree,
5787
 
                                                      best_param_idx,
5788
 
                                                      best_quick_prefix_records);
 
5775
    new(param->mem_root) optimizer::GroupMinMaxReadPlan(have_min,
 
5776
                                                        have_max,
 
5777
                                                        min_max_arg_part,
 
5778
                                                        group_prefix_len,
 
5779
                                                        used_key_parts,
 
5780
                                                        group_key_parts,
 
5781
                                                        index_info,
 
5782
                                                        index,
 
5783
                                                        key_infix_len,
 
5784
                                                        (key_infix_len > 0) ? key_infix : NULL,
 
5785
                                                        tree,
 
5786
                                                        best_index_tree,
 
5787
                                                        best_param_idx,
 
5788
                                                        best_quick_prefix_records);
5789
5789
  if (read_plan)
5790
5790
  {
5791
5791
    if (tree && read_plan->quick_prefix_records == 0)
6117
6117
    records             [out] The number of rows retrieved
6118
6118
 
6119
6119
  DESCRIPTION
6120
 
    This method computes the access cost of a TRP_GROUP_MIN_MAX instance and
 
6120
    This method computes the access cost of a GroupMinMaxReadPlan instance and
6121
6121
    the number of rows returned. It updates this->read_cost and this->records.
6122
6122
 
6123
6123
  NOTES
6241
6241
  Construct a new quick select object for queries with group by with min/max.
6242
6242
 
6243
6243
  SYNOPSIS
6244
 
    TRP_GROUP_MIN_MAX::make_quick()
 
6244
    GroupMinMaxReadPlan::make_quick()
6245
6245
    param              Parameter from test_quick_select
6246
6246
    retrieve_full_rows ignored
6247
6247
    parent_alloc       Memory pool to use, if any.
6258
6258
    NULL otherwise.
6259
6259
*/
6260
6260
optimizer::QuickSelectInterface *
6261
 
optimizer::TRP_GROUP_MIN_MAX::make_quick(optimizer::Parameter *param, bool, memory::Root *parent_alloc)
 
6261
optimizer::GroupMinMaxReadPlan::make_quick(optimizer::Parameter *param, bool, memory::Root *parent_alloc)
6262
6262
{
6263
6263
  optimizer::QuickGroupMinMaxSelect *quick= NULL;
6264
6264
 
6346
6346
}
6347
6347
 
6348
6348
 
6349
 
optimizer::QuickSelectInterface *optimizer::TRP_RANGE::make_quick(optimizer::Parameter *param, bool, memory::Root *parent_alloc)
 
6349
optimizer::QuickSelectInterface *optimizer::RangeReadPlan::make_quick(optimizer::Parameter *param, bool, memory::Root *parent_alloc)
6350
6350
{
6351
6351
  optimizer::QuickRangeSelect *quick= NULL;
6352
6352
  if ((quick= optimizer::get_quick_select(param,