142
145
static unsigned char is_null_string[2]= {1,0};
149
Get cost of reading nrows table records in a "disk sweep"
151
A disk sweep read is a sequence of Cursor->rnd_pos(rowid) calls that made
152
for an ordered sequence of rowids.
154
We assume hard disk IO. The read is performed as follows:
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
160
Time to do #3 is insignificant compared to #2+#1.
162
Time to move the disk head is proportional to head travel distance.
164
Time to wait for the plate to rotate depends on whether the disk head
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.
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.
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:
180
1 = half_rotation_cost + move_cost * 1/3 * typical_data_file_length
182
We define half_rotation_cost as DISK_SEEK_BASE_COST=0.9.
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.
191
static void get_sweep_read_cost(Table *table, ha_rows nrows, bool interrupted,
195
if (table->file->primary_key_is_clustered())
197
cost->io_count= table->file->read_time(table->s->primary_key,
198
(uint32_t) nrows, nrows);
203
ceil(uint64_t2double(table->file->stats.data_file_length) / IO_SIZE);
205
n_blocks * (1.0 - pow(1.0 - 1.0/n_blocks, rows2double(nrows)));
206
if (busy_blocks < 1.0)
209
cost->io_count= busy_blocks;
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);
144
220
class RANGE_OPT_PARAM;
146
222
A construction block of the SEL_ARG-graph.
1292
1368
QUICK_RANGE_SELECT::init_ror_merged_scan()
1293
1369
reuse_handler If true, use head->file, otherwise create a separate
1297
This function creates and prepares for subsequent use a separate handler
1373
This function creates and prepares for subsequent use a separate Cursor
1298
1374
object if it can't reuse head->file. The reason for this is that during
1299
1375
ROR-merge several key scans are performed simultaneously, and a single
1300
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.
1302
1378
In ROR-merge the quick select doing merge does full records retrieval,
1303
1379
merged quick selects read only keys.
7145
7221
last_range= NULL;
7146
7222
cur_range= (QUICK_RANGE**) ranges.buffer;
7148
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)))
7151
7227
/* Allocate buffer if we need one but haven't allocated it yet */
7152
7228
if (mrr_buf_size && !mrr_buf_desc)
7154
7230
buf_size= mrr_buf_size;
7155
while (buf_size && !my_multi_malloc(MYF(MY_WME),
7231
while (buf_size && ! memory::multi_malloc(false,
7156
7232
&mrr_buf_desc, sizeof(*mrr_buf_desc),
7157
7233
&mrange_buff, buf_size,
7163
7239
if (!mrr_buf_desc)
7164
7240
return(HA_ERR_OUT_OF_MEM);
7166
/* Initialize the handler buffer. */
7242
/* Initialize the Cursor buffer. */
7167
7243
mrr_buf_desc->buffer= mrange_buff;
7168
7244
mrr_buf_desc->buffer_end= mrange_buff + buf_size;
7169
7245
mrr_buf_desc->end_of_used_area= mrange_buff;