~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/optimizer/range.cc

edit

Show diffs side-by-side

added added

removed removed

Lines of Context:
100
100
           subject and may omit some details.
101
101
*/
102
102
 
103
 
#include <config.h>
 
103
#include "config.h"
104
104
 
105
105
#include <math.h>
106
106
#include <float.h>
111
111
 
112
112
#include <boost/dynamic_bitset.hpp>
113
113
 
114
 
#include <drizzled/check_stack_overrun.h>
115
 
#include <drizzled/error.h>
116
 
#include <drizzled/field/num.h>
117
 
#include <drizzled/internal/iocache.h>
118
 
#include <drizzled/internal/my_sys.h>
119
 
#include <drizzled/item/cmpfunc.h>
120
 
#include <drizzled/optimizer/cost_vector.h>
121
 
#include <drizzled/optimizer/quick_group_min_max_select.h>
122
 
#include <drizzled/optimizer/quick_index_merge_select.h>
123
 
#include <drizzled/optimizer/quick_range.h>
124
 
#include <drizzled/optimizer/quick_range_select.h>
125
 
#include <drizzled/optimizer/quick_ror_intersect_select.h>
126
 
#include <drizzled/optimizer/quick_ror_union_select.h>
127
 
#include <drizzled/optimizer/range.h>
128
 
#include <drizzled/optimizer/range_param.h>
129
 
#include <drizzled/optimizer/sel_arg.h>
130
 
#include <drizzled/optimizer/sel_imerge.h>
131
 
#include <drizzled/optimizer/sel_tree.h>
132
 
#include <drizzled/optimizer/sum.h>
133
 
#include <drizzled/optimizer/table_read_plan.h>
134
 
#include <drizzled/plugin/storage_engine.h>
135
 
#include <drizzled/records.h>
136
 
#include <drizzled/sql_base.h>
137
 
#include <drizzled/sql_select.h>
138
 
#include <drizzled/table_reference.h>
139
 
#include <drizzled/session.h>
140
 
 
141
 
#include <drizzled/unique.h>
142
 
 
143
 
#include <drizzled/temporal.h> /* Needed in get_mm_leaf() for timestamp -> datetime comparisons */
 
114
#include "drizzled/sql_base.h"
 
115
#include "drizzled/sql_select.h"
 
116
#include "drizzled/error.h"
 
117
#include "drizzled/optimizer/cost_vector.h"
 
118
#include "drizzled/item/cmpfunc.h"
 
119
#include "drizzled/field/num.h"
 
120
#include "drizzled/check_stack_overrun.h"
 
121
#include "drizzled/optimizer/sum.h"
 
122
#include "drizzled/optimizer/range.h"
 
123
#include "drizzled/optimizer/quick_range.h"
 
124
#include "drizzled/optimizer/quick_range_select.h"
 
125
#include "drizzled/optimizer/quick_group_min_max_select.h"
 
126
#include "drizzled/optimizer/quick_index_merge_select.h"
 
127
#include "drizzled/optimizer/quick_ror_intersect_select.h"
 
128
#include "drizzled/optimizer/quick_ror_union_select.h"
 
129
#include "drizzled/optimizer/table_read_plan.h"
 
130
#include "drizzled/optimizer/sel_arg.h"
 
131
#include "drizzled/optimizer/sel_imerge.h"
 
132
#include "drizzled/optimizer/sel_tree.h"
 
133
#include "drizzled/optimizer/range_param.h"
 
134
#include "drizzled/records.h"
 
135
#include "drizzled/internal/my_sys.h"
 
136
#include "drizzled/internal/iocache.h"
 
137
 
 
138
#include "drizzled/temporal.h" /* Needed in get_mm_leaf() for timestamp -> datetime comparisons */
144
139
 
145
140
using namespace std;
146
141
namespace drizzled
218
213
  else
219
214
  {
220
215
    double n_blocks=
221
 
      ceil(static_cast<double>(table->cursor->stats.data_file_length) / IO_SIZE);
 
216
      ceil(uint64_t2double(table->cursor->stats.data_file_length) / IO_SIZE);
222
217
    double busy_blocks=
223
 
      n_blocks * (1.0 - pow(1.0 - 1.0/n_blocks, static_cast<double>(nrows)));
 
218
      n_blocks * (1.0 - pow(1.0 - 1.0/n_blocks, rows2double(nrows)));
224
219
    if (busy_blocks < 1.0)
225
220
      busy_blocks= 1.0;
226
221
 
742
737
    {
743
738
      int key_for_use= head->find_shortest_key(&head->covering_keys);
744
739
      double key_read_time=
745
 
        param.table->cursor->index_only_read_time(key_for_use, records) +
 
740
        param.table->cursor->index_only_read_time(key_for_use,
 
741
                                                rows2double(records)) +
746
742
        (double) records / TIME_FOR_COMPARE;
747
743
      if (key_read_time < read_time)
748
744
        read_time= key_read_time;
812
808
          objects are not allowed so don't use ROR-intersection for
813
809
          table deletes.
814
810
        */
815
 
        if ((session->getLex()->sql_command != SQLCOM_DELETE))
 
811
        if ((session->lex->sql_command != SQLCOM_DELETE))
816
812
        {
817
813
          /*
818
814
            Get best non-covering ROR-intersection plan and prepare data for
840
836
        optimizer::SEL_IMERGE *imerge= NULL;
841
837
        optimizer::TableReadPlan *best_conj_trp= NULL;
842
838
        optimizer::TableReadPlan *new_conj_trp= NULL;
843
 
        List<optimizer::SEL_IMERGE>::iterator it(tree->merges.begin());
 
839
        List_iterator_fast<optimizer::SEL_IMERGE> it(tree->merges);
844
840
        while ((imerge= it++))
845
841
        {
846
842
          new_conj_trp= get_best_disjunct_quick(session, &param, imerge, best_read_time);
1045
1041
  /* Calculate cost(rowid_to_row_scan) */
1046
1042
  {
1047
1043
    optimizer::CostVector sweep_cost;
1048
 
    Join *join= param->session->getLex()->select_lex.join;
 
1044
    Join *join= param->session->lex->select_lex.join;
1049
1045
    bool is_interrupted= test(join && join->tables == 1);
1050
1046
    get_sweep_read_cost(param->table, non_cpk_scan_records, is_interrupted,
1051
1047
                        &sweep_cost);
1088
1084
  }
1089
1085
 
1090
1086
build_ror_index_merge:
1091
 
  if (!all_scans_ror_able || param->session->getLex()->sql_command == SQLCOM_DELETE)
 
1087
  if (!all_scans_ror_able || param->session->lex->sql_command == SQLCOM_DELETE)
1092
1088
    return(imerge_trp);
1093
1089
 
1094
1090
  /* Ok, it is possible to build a ROR-union, try it. */
1121
1117
      cost= param->table->cursor->
1122
1118
              read_time(param->real_keynr[(*cur_child)->key_idx], 1,
1123
1119
                        (*cur_child)->records) +
1124
 
              static_cast<double>((*cur_child)->records) / TIME_FOR_COMPARE;
 
1120
              rows2double((*cur_child)->records) / TIME_FOR_COMPARE;
1125
1121
    }
1126
1122
    else
1127
1123
      cost= read_time;
1163
1159
  double roru_total_cost;
1164
1160
  {
1165
1161
    optimizer::CostVector sweep_cost;
1166
 
    Join *join= param->session->getLex()->select_lex.join;
 
1162
    Join *join= param->session->lex->select_lex.join;
1167
1163
    bool is_interrupted= test(join && join->tables == 1);
1168
1164
    get_sweep_read_cost(param->table, roru_total_records, is_interrupted,
1169
1165
                        &sweep_cost);
1170
1166
    roru_total_cost= roru_index_costs +
1171
 
                     static_cast<double>(roru_total_records)*log((double)n_child_scans) /
 
1167
                     rows2double(roru_total_records)*log((double)n_child_scans) /
1172
1168
                     (TIME_FOR_COMPARE_ROWID * M_LN2) +
1173
1169
                     sweep_cost.total_cost();
1174
1170
  }
1234
1230
    if (param->needed_fields.test(key_part->fieldnr-1))
1235
1231
      tmp_bitset.set(key_part->fieldnr-1);
1236
1232
  }
1237
 
  double rows= param->table->quick_rows[ror_scan->keynr];
 
1233
  double rows= rows2double(param->table->quick_rows[ror_scan->keynr]);
1238
1234
  ror_scan->index_read_cost=
1239
1235
    param->table->cursor->index_only_read_time(ror_scan->keynr, rows);
1240
1236
  ror_scan->covered_fields= tmp_bitset.to_ulong();
1257
1253
 
1258
1254
static int cmp_ror_scan_info(optimizer::RorScanInfo** a, optimizer::RorScanInfo** b)
1259
1255
{
1260
 
  double val1= static_cast<double>((*a)->records) * (*a)->key_rec_length;
1261
 
  double val2= static_cast<double>((*b)->records) * (*b)->key_rec_length;
 
1256
  double val1= rows2double((*a)->records) * (*a)->key_rec_length;
 
1257
  double val2= rows2double((*b)->records) * (*b)->key_rec_length;
1262
1258
  return (val1 < val2)? -1: (val1 == val2)? 0 : 1;
1263
1259
}
1264
1260
 
1494
1490
      if (cur_covered)
1495
1491
      {
1496
1492
        /* uncovered -> covered */
1497
 
        selectivity_mult *= static_cast<double>(records) / prev_records;
 
1493
        double tmp= rows2double(records)/rows2double(prev_records);
 
1494
        selectivity_mult *= tmp;
1498
1495
        prev_records= HA_POS_ERROR;
1499
1496
      }
1500
1497
      else
1507
1504
  }
1508
1505
  if (!prev_covered)
1509
1506
  {
1510
 
    selectivity_mult *= static_cast<double>(info->param->table->quick_rows[scan->keynr]) / prev_records;
 
1507
    double tmp= rows2double(info->param->table->quick_rows[scan->keynr]) /
 
1508
                rows2double(prev_records);
 
1509
    selectivity_mult *= tmp;
1511
1510
  }
1512
 
  return selectivity_mult;
 
1511
  return(selectivity_mult);
1513
1512
}
1514
1513
 
1515
1514
 
1570
1569
      each record of every scan. Assuming 1/TIME_FOR_COMPARE_ROWID
1571
1570
      per check this gives us:
1572
1571
    */
1573
 
    info->index_scan_costs += static_cast<double>(info->index_records) /
 
1572
    info->index_scan_costs += rows2double(info->index_records) /
1574
1573
                              TIME_FOR_COMPARE_ROWID;
1575
1574
  }
1576
1575
  else
1589
1588
  if (! info->is_covering)
1590
1589
  {
1591
1590
    optimizer::CostVector sweep_cost;
1592
 
    Join *join= info->param->session->getLex()->select_lex.join;
 
1591
    Join *join= info->param->session->lex->select_lex.join;
1593
1592
    bool is_interrupted= test(join && join->tables == 1);
1594
1593
    get_sweep_read_cost(info->param->table, double2rows(info->out_rows),
1595
1594
                        is_interrupted, &sweep_cost);
1703
1702
    cost total_cost.
1704
1703
  */
1705
1704
  /* Add priority queue use cost. */
1706
 
  total_cost += static_cast<double>(records) *
 
1705
  total_cost += rows2double(records)*
1707
1706
                log((double)(ror_scan_mark - tree->ror_scans)) /
1708
1707
                (TIME_FOR_COMPARE_ROWID * M_LN2);
1709
1708
 
2565
2564
 
2566
2565
  if (cond->type() == Item::COND_ITEM)
2567
2566
  {
2568
 
    List<Item>::iterator li(((Item_cond*) cond)->argument_list()->begin());
 
2567
    List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
2569
2568
 
2570
2569
    if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
2571
2570
    {
2977
2976
   * it is, then we must convert to the highest Timestamp value (or lowest,
2978
2977
   * depending on whether the datetime is before or after the epoch.
2979
2978
   */
2980
 
  if (field->is_timestamp())
 
2979
  if (field->type() == DRIZZLE_TYPE_TIMESTAMP)
2981
2980
  {
2982
2981
    /*
2983
2982
     * The left-side of the range comparison is a timestamp field.  Therefore,
3258
3257
 
3259
3258
#define CLONE_KEY1_MAYBE 1
3260
3259
#define CLONE_KEY2_MAYBE 2
 
3260
#define swap_clone_flag(A) ((A & 1) << 1) | ((A & 2) >> 1)
3261
3261
 
3262
 
static uint32_t swap_clone_flag(uint32_t a)
3263
 
{
3264
 
  return ((a & 1) << 1) | ((a & 2) >> 1);
3265
 
}
3266
3262
 
3267
3263
static optimizer::SEL_TREE *
3268
3264
tree_and(optimizer::RangeParameter *param, optimizer::SEL_TREE *tree1, optimizer::SEL_TREE *tree2)
3314
3310
  /* dispose index_merge if there is a "range" option */
3315
3311
  if (result_keys.any())
3316
3312
  {
3317
 
    tree1->merges.clear();
 
3313
    tree1->merges.empty();
3318
3314
    return(tree1);
3319
3315
  }
3320
3316
 
3859
3855
      !(pk_is_clustered && keynr == param->table->getShare()->getPrimaryKey()))
3860
3856
     *mrr_flags |= HA_MRR_INDEX_ONLY;
3861
3857
 
3862
 
  if (session->getLex()->sql_command != SQLCOM_SELECT)
 
3858
  if (session->lex->sql_command != SQLCOM_SELECT)
3863
3859
    *mrr_flags |= HA_MRR_USE_DEFAULT_IMPL;
3864
3860
 
3865
3861
  *bufsize= param->session->variables.read_rnd_buff_size;
4319
4315
  /* Call multi_range_read_info() to get the MRR flags and buffer size */
4320
4316
  quick->mrr_flags= HA_MRR_NO_ASSOCIATION |
4321
4317
                    (table->key_read ? HA_MRR_INDEX_ONLY : 0);
4322
 
  if (session->getLex()->sql_command != SQLCOM_SELECT)
 
4318
  if (session->lex->sql_command != SQLCOM_SELECT)
4323
4319
    quick->mrr_flags |= HA_MRR_USE_DEFAULT_IMPL;
4324
4320
 
4325
4321
  quick->mrr_buf_size= session->variables.read_rnd_buff_size;
4567
4563
get_best_group_min_max(optimizer::Parameter *param, optimizer::SEL_TREE *tree)
4568
4564
{
4569
4565
  Session *session= param->session;
4570
 
  Join *join= session->getLex()->current_select->join;
 
4566
  Join *join= session->lex->current_select->join;
4571
4567
  Table *table= param->table;
4572
4568
  bool have_min= false;              /* true if there is a MIN function. */
4573
4569
  bool have_max= false;              /* true if there is a MAX function. */
4599
4595
    return NULL;
4600
4596
 
4601
4597
  /* Analyze the query in more detail. */
4602
 
  List<Item>::iterator select_items_it(join->fields_list.begin());
 
4598
  List_iterator<Item> select_items_it(join->fields_list);
4603
4599
 
4604
4600
  /* Check (SA1,SA4) and store the only MIN/MAX argument - the C attribute.*/
4605
4601
  if (join->make_sum_func_list(join->all_fields, join->fields_list, 1))
4755
4751
    */
4756
4752
    else if (join->select_distinct)
4757
4753
    {
4758
 
      select_items_it= join->fields_list.begin();
 
4754
      select_items_it.rewind();
4759
4755
      used_key_parts_map.reset();
4760
4756
      uint32_t max_key_part= 0;
4761
4757
      while ((item= select_items_it++))
5036
5032
  Item::Type cond_type= cond->type();
5037
5033
  if (cond_type == Item::COND_ITEM) /* 'AND' or 'OR' */
5038
5034
  {
5039
 
    List<Item>::iterator li(((Item_cond*) cond)->argument_list()->begin());
 
5035
    List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
5040
5036
    Item *and_or_arg= NULL;
5041
5037
    while ((and_or_arg= li++))
5042
5038
    {
5471
5467
  optimizer::QuickGroupMinMaxSelect *quick= NULL;
5472
5468
 
5473
5469
  quick= new optimizer::QuickGroupMinMaxSelect(param->table,
5474
 
                                               param->session->getLex()->current_select->join,
 
5470
                                               param->session->lex->current_select->join,
5475
5471
                                               have_min,
5476
5472
                                               have_max,
5477
5473
                                               min_max_arg_part,