~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/opt_range.cc

  • Committer: Brian Aker
  • Date: 2009-10-16 10:27:33 UTC
  • mfrom: (1183.1.4 merge)
  • Revision ID: brian@gaz-20091016102733-b10po5oup0hjlilh
MergeĀ EngineĀ changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
136
136
 
137
137
extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b)
138
138
{
139
 
  handler *file= (handler*)arg;
 
139
  Cursor *file= (Cursor*)arg;
140
140
  return file->cmp_ref((const unsigned char*)a, (const unsigned char*)b);
141
141
}
142
142
 
144
144
 
145
145
static unsigned char is_null_string[2]= {1,0};
146
146
 
 
147
 
 
148
/**
 
149
  Get cost of reading nrows table records in a "disk sweep"
 
150
 
 
151
  A disk sweep read is a sequence of Cursor->rnd_pos(rowid) calls that made
 
152
  for an ordered sequence of rowids.
 
153
 
 
154
  We assume hard disk IO. The read is performed as follows:
 
155
 
 
156
   1. The disk head is moved to the needed cylinder
 
157
   2. The controller waits for the plate to rotate
 
158
   3. The data is transferred
 
159
 
 
160
  Time to do #3 is insignificant compared to #2+#1.
 
161
 
 
162
  Time to move the disk head is proportional to head travel distance.
 
163
 
 
164
  Time to wait for the plate to rotate depends on whether the disk head
 
165
  was moved or not.
 
166
 
 
167
  If disk head wasn't moved, the wait time is proportional to distance
 
168
  between the previous block and the block we're reading.
 
169
 
 
170
  If the head was moved, we don't know how much we'll need to wait for the
 
171
  plate to rotate. We assume the wait time to be a variate with a mean of
 
172
  0.5 of full rotation time.
 
173
 
 
174
  Our cost units are "random disk seeks". The cost of random disk seek is
 
175
  actually not a constant, it depends one range of cylinders we're going
 
176
  to access. We make it constant by introducing a fuzzy concept of "typical
 
177
  datafile length" (it's fuzzy as it's hard to tell whether it should
 
178
  include index file, temp.tables etc). Then random seek cost is:
 
179
 
 
180
    1 = half_rotation_cost + move_cost * 1/3 * typical_data_file_length
 
181
 
 
182
  We define half_rotation_cost as DISK_SEEK_BASE_COST=0.9.
 
183
 
 
184
  @param table             Table to be accessed
 
185
  @param nrows             Number of rows to retrieve
 
186
  @param interrupted       true <=> Assume that the disk sweep will be
 
187
                           interrupted by other disk IO. false - otherwise.
 
188
  @param cost         OUT  The cost.
 
189
*/
 
190
 
 
191
static void get_sweep_read_cost(Table *table, ha_rows nrows, bool interrupted,
 
192
                                COST_VECT *cost)
 
193
{
 
194
  cost->zero();
 
195
  if (table->file->primary_key_is_clustered())
 
196
  {
 
197
    cost->io_count= table->file->read_time(table->s->primary_key,
 
198
                                           (uint32_t) nrows, nrows);
 
199
  }
 
200
  else
 
201
  {
 
202
    double n_blocks=
 
203
      ceil(uint64_t2double(table->file->stats.data_file_length) / IO_SIZE);
 
204
    double busy_blocks=
 
205
      n_blocks * (1.0 - pow(1.0 - 1.0/n_blocks, rows2double(nrows)));
 
206
    if (busy_blocks < 1.0)
 
207
      busy_blocks= 1.0;
 
208
 
 
209
    cost->io_count= busy_blocks;
 
210
 
 
211
    if (!interrupted)
 
212
    {
 
213
      /* Assume reading is done in one 'sweep' */
 
214
      cost->avg_io_cost= (DISK_SEEK_BASE_COST +
 
215
                          DISK_SEEK_PROP_COST*n_blocks/busy_blocks);
 
216
    }
 
217
  }
 
218
}
 
219
 
147
220
class RANGE_OPT_PARAM;
148
221
/*
149
222
  A construction block of the SEL_ARG-graph.
1159
1232
 
1160
1233
int QUICK_RANGE_SELECT::init()
1161
1234
{
1162
 
  if (file->inited != handler::NONE)
 
1235
  if (file->inited != Cursor::NONE)
1163
1236
    file->ha_index_or_rnd_end();
1164
1237
  return(file->ha_index_init(index, 1));
1165
1238
}
1167
1240
 
1168
1241
void QUICK_RANGE_SELECT::range_end()
1169
1242
{
1170
 
  if (file->inited != handler::NONE)
 
1243
  if (file->inited != Cursor::NONE)
1171
1244
    file->ha_index_or_rnd_end();
1172
1245
}
1173
1246
 
1294
1367
  SYNOPSIS
1295
1368
    QUICK_RANGE_SELECT::init_ror_merged_scan()
1296
1369
      reuse_handler If true, use head->file, otherwise create a separate
1297
 
                    handler object
 
1370
                    Cursor object
1298
1371
 
1299
1372
  NOTES
1300
 
    This function creates and prepares for subsequent use a separate handler
 
1373
    This function creates and prepares for subsequent use a separate Cursor
1301
1374
    object if it can't reuse head->file. The reason for this is that during
1302
1375
    ROR-merge several key scans are performed simultaneously, and a single
1303
 
    handler is only capable of preserving context of a single key scan.
 
1376
    Cursor is only capable of preserving context of a single key scan.
1304
1377
 
1305
1378
    In ROR-merge the quick select doing merge does full records retrieval,
1306
1379
    merged quick selects read only keys.
1312
1385
 
1313
1386
int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler)
1314
1387
{
1315
 
  handler *save_file= file, *org_file;
 
1388
  Cursor *save_file= file, *org_file;
1316
1389
  Session *session;
1317
1390
 
1318
1391
  in_ror_merged_scan= 1;
1326
1399
    goto end;
1327
1400
  }
1328
1401
 
1329
 
  /* Create a separate handler object for this quick select */
 
1402
  /* Create a separate Cursor object for this quick select */
1330
1403
  if (free_file)
1331
1404
  {
1332
 
    /* already have own 'handler' object. */
 
1405
    /* already have own 'Cursor' object. */
1333
1406
    return 0;
1334
1407
  }
1335
1408
 
1403
1476
  SYNOPSIS
1404
1477
    QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan()
1405
1478
      reuse_handler If true, use head->file, otherwise create separate
1406
 
                    handler object.
 
1479
                    Cursor object.
1407
1480
  RETURN
1408
1481
    0     OK
1409
1482
    other error code
1491
1564
  quick_selects.delete_elements();
1492
1565
  delete cpk_quick;
1493
1566
  free_root(&alloc,MYF(0));
1494
 
  if (need_to_fetch_row && head->file->inited != handler::NONE)
 
1567
  if (need_to_fetch_row && head->file->inited != Cursor::NONE)
1495
1568
    head->file->ha_rnd_end();
1496
1569
  return;
1497
1570
}
1616
1689
    queue->pop();
1617
1690
  delete queue;
1618
1691
  quick_selects.delete_elements();
1619
 
  if (head->file->inited != handler::NONE)
 
1692
  if (head->file->inited != Cursor::NONE)
1620
1693
    head->file->ha_rnd_end();
1621
1694
  free_root(&alloc,MYF(0));
1622
1695
  return;
2363
2436
        }
2364
2437
 
2365
2438
        /*
2366
 
          Simultaneous key scans and row deletes on several handler
 
2439
          Simultaneous key scans and row deletes on several Cursor
2367
2440
          objects are not allowed so don't use ROR-intersection for
2368
2441
          table deletes.
2369
2442
        */
6315
6388
 
6316
6389
  RETURN
6317
6390
    Estimate # of records to be retrieved.
6318
 
    HA_POS_ERROR if estimate calculation failed due to table handler problems.
 
6391
    HA_POS_ERROR if estimate calculation failed due to table Cursor problems.
6319
6392
*/
6320
6393
 
6321
6394
static
6325
6398
{
6326
6399
  SEL_ARG_RANGE_SEQ seq;
6327
6400
  RANGE_SEQ_IF seq_if = {sel_arg_range_seq_init, sel_arg_range_seq_next};
6328
 
  handler *file= param->table->file;
 
6401
  Cursor *file= param->table->file;
6329
6402
  ha_rows rows;
6330
6403
  uint32_t keynr= param->real_keynr[idx];
6331
6404
 
6876
6949
  QUICK_RANGE_SELECT* cur_quick;
6877
6950
  int result;
6878
6951
  Unique *unique;
6879
 
  handler *file= head->file;
 
6952
  Cursor *file= head->file;
6880
6953
 
6881
6954
  file->extra(HA_EXTRA_KEYREAD);
6882
6955
  head->prepare_for_position();
6886
6959
  assert(cur_quick != 0);
6887
6960
 
6888
6961
  /*
6889
 
    We reuse the same instance of handler so we need to call both init and
 
6962
    We reuse the same instance of Cursor so we need to call both init and
6890
6963
    reset here.
6891
6964
  */
6892
6965
  if (cur_quick->init() || cur_quick->reset())
6906
6979
      if (!cur_quick)
6907
6980
        break;
6908
6981
 
6909
 
      if (cur_quick->file->inited != handler::NONE)
 
6982
      if (cur_quick->file->inited != Cursor::NONE)
6910
6983
        cur_quick->file->ha_index_end();
6911
6984
      if (cur_quick->init() || cur_quick->reset())
6912
6985
        return 0;
7148
7221
  last_range= NULL;
7149
7222
  cur_range= (QUICK_RANGE**) ranges.buffer;
7150
7223
 
7151
 
  if (file->inited == handler::NONE && (error= file->ha_index_init(index,1)))
 
7224
  if (file->inited == Cursor::NONE && (error= file->ha_index_init(index,1)))
7152
7225
    return(error);
7153
7226
 
7154
7227
  /* Allocate buffer if we need one but haven't allocated it yet */
7166
7239
    if (!mrr_buf_desc)
7167
7240
      return(HA_ERR_OUT_OF_MEM);
7168
7241
 
7169
 
    /* Initialize the handler buffer. */
 
7242
    /* Initialize the Cursor buffer. */
7170
7243
    mrr_buf_desc->buffer= mrange_buff;
7171
7244
    mrr_buf_desc->buffer_end= mrange_buff + buf_size;
7172
7245
    mrr_buf_desc->end_of_used_area= mrange_buff;
9015
9088
 
9016
9089
QUICK_GROUP_MIN_MAX_SELECT::~QUICK_GROUP_MIN_MAX_SELECT()
9017
9090
{
9018
 
  if (file->inited != handler::NONE)
 
9091
  if (file->inited != Cursor::NONE)
9019
9092
    file->ha_index_end();
9020
9093
  if (min_max_arg_part)
9021
9094
    delete_dynamic(&min_max_ranges);