Commit e0999cdf authored by Sergey Petrunya's avatar Sergey Petrunya

DS-MRR support improvements (MWL#123, MWL#124, MWL#125)

- Lots of TODO comments
- add mrr_sort_keys flag to @@optimizer_switch
- [from Igor] SQL layer part passes HA_MRR_MATERIALIZED_KEYS flag
- Don't call rnd_pos() many times in a row if sorted rowid buffer
  has the same rowid value for multiple consequive (rowid, range_id) pairs.
parent e1006e9e
......@@ -4,19 +4,19 @@
#
select @@optimizer_switch;
@@optimizer_switch
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr_sort_keys=on
set optimizer_switch='index_merge=off,index_merge_union=off';
select @@optimizer_switch;
@@optimizer_switch
index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on
index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr_sort_keys=on
set optimizer_switch='index_merge_union=on';
select @@optimizer_switch;
@@optimizer_switch
index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on
index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr_sort_keys=on
set optimizer_switch='default,index_merge_sort_union=off';
select @@optimizer_switch;
@@optimizer_switch
index_merge=on,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on
index_merge=on,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr_sort_keys=on
set optimizer_switch=4;
ERROR 42000: Variable 'optimizer_switch' can't be set to the value of '4'
set optimizer_switch=NULL;
......@@ -43,57 +43,57 @@ set optimizer_switch=default;
set optimizer_switch='index_merge=off,index_merge_union=off,default';
select @@optimizer_switch;
@@optimizer_switch
index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on
index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr_sort_keys=on
set optimizer_switch=default;
select @@global.optimizer_switch;
@@global.optimizer_switch
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr_sort_keys=on
set @@global.optimizer_switch=default;
select @@global.optimizer_switch;
@@global.optimizer_switch
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr_sort_keys=on
#
# Check index_merge's @@optimizer_switch flags
#
select @@optimizer_switch;
@@optimizer_switch
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr_sort_keys=on
BUG#37120 optimizer_switch allowable values not according to specification
select @@optimizer_switch;
@@optimizer_switch
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr_sort_keys=on
set optimizer_switch='default,materialization=off';
select @@optimizer_switch;
@@optimizer_switch
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=off,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=off,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr_sort_keys=on
set optimizer_switch='default,semijoin=off';
select @@optimizer_switch;
@@optimizer_switch
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr_sort_keys=on
set optimizer_switch='default,loosescan=off';
select @@optimizer_switch;
@@optimizer_switch
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=off,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=off,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr_sort_keys=on
set optimizer_switch='default,semijoin=off,materialization=off';
select @@optimizer_switch;
@@optimizer_switch
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=off,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=off,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr_sort_keys=on
set optimizer_switch='default,materialization=off,semijoin=off';
select @@optimizer_switch;
@@optimizer_switch
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=off,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=off,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr_sort_keys=on
set optimizer_switch='default,semijoin=off,materialization=off,loosescan=off';
select @@optimizer_switch;
@@optimizer_switch
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=off,materialization=off,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=off,materialization=off,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr_sort_keys=on
set optimizer_switch='default,semijoin=off,loosescan=off';
select @@optimizer_switch;
@@optimizer_switch
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=off,materialization=on,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=off,materialization=on,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr_sort_keys=on
set optimizer_switch='default,materialization=off,loosescan=off';
select @@optimizer_switch;
@@optimizer_switch
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=off,materialization=off,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=off,materialization=off,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr_sort_keys=on
set optimizer_switch=default;
......@@ -1322,6 +1322,12 @@ void get_sweep_read_cost(TABLE *table, ha_rows nrows, bool interrupted,
*/
#define HA_MRR_NO_NULL_ENDPOINTS 128
/*
The MRR user has materialized range keys somewhere in the user's buffer.
This can be used for optimization of the procedure that sorts these keys
since in this case key values don't have to be copied into the MRR buffer.
*/
#define HA_MRR_MATERIALIZED_KEYS 256
/*
......
......@@ -327,24 +327,62 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
mode, buf);
DBUG_RETURN(retval);
}
mrr_buf= buf->buffer;
use_default_impl= FALSE;
is_mrr_assoc= !test(mode & HA_MRR_NO_ASSOCIATION);
if (is_mrr_assoc)
status_var_increment(table->in_use->status_var.ha_multi_range_read_init_count);
// psergey2: split the buffer:
/*
psergey2-note: we can't split the buffer here because we don't know how key
length. we'll only be able to do it when we've got the first range.
if ((mrr_flags & HA_MRR_SINGLE_POINT) &&
optimizer_flag(thd, OPTIMIZER_SWITCH_MRR_SORT_KEYS))
{
do_sort_keys= TRUE; // will use key buffer to sort keys;
bool use_key_pointers= test(mrr_flags & HA_MRR_MATERIALIZED_KEYS);
}
do_rowid_fetch= FALSE;
if (!doing_cpk_scan && !index_only_read)
{
do_rowid_fetch= TRUE; //will use rowid buffer to store/sort rowids, etc
}
if (do_sort_keys && do_rowid_fetch)
{
split buffer space proportionally
}
else
{
// give all space to one buffer
if (do_sort_keys)
{
//sort_buffer_start= ...;
}
else
{
DBUG_ASSERT(do_rowid_fetch);
//rowid_buffer_start= ...;
}
}
*/
mrr_buf= buf->buffer;
mrr_buf_end= buf->buffer_end;
if (is_mrr_assoc)
status_var_increment(table->in_use->status_var.ha_multi_range_read_init_count);
if ((doing_cpk_scan= check_cpk_scan(h->active_index, mode)))
{
/* It's a DS-MRR/CPK scan */
cpk_tuple_length= 0; /* dummy value telling it needs to be inited */
cpk_have_range= FALSE;
use_default_impl= FALSE;
h->mrr_iter= seq_funcs->init(seq_init_param, n_ranges, mode);
h->mrr_funcs= *seq_funcs;
dsmrr_fill_buffer_cpk();
dsmrr_fill_key_buffer();
if (dsmrr_eof)
buf->end_of_used_area= mrr_buf_last;
DBUG_RETURN(0); /* nothing could go wrong while filling the buffer */
......@@ -355,6 +393,11 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
mrr_buf_last= mrr_buf + ((mrr_buf_end - mrr_buf)/ elem_size)* elem_size;
mrr_buf_end= mrr_buf_last;
/*
psergey2: this is only needed when
- doing a rowid-to-row scan
- the buffer wasn't exhausted on the first pass.
*/
/*
There can be two cases:
- This is the first call since index_init(), h2==NULL
......@@ -365,7 +408,7 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
*/
if (!h2)
{
/* Create a separate handler object to do rndpos() calls. */
/* Create a separate handler object to do rnd_pos() calls. */
THD *thd= current_thd;
/*
::clone() takes up a lot of stack, especially on 64 bit platforms.
......@@ -376,7 +419,7 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
DBUG_ASSERT(h->active_index != MAX_KEY);
uint mrr_keyno= h->active_index;
/* Create a separate handler object to do rndpos() calls. */
/* Create a separate handler object to do rnd_pos() calls. */
if (!(new_h2= h->clone(thd->mem_root)) ||
new_h2->ha_external_lock(thd, F_RDLCK))
{
......@@ -397,6 +440,7 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
goto error;
}
use_default_impl= FALSE;
h2= new_h2; /* Ok, now can put it into h2 */
table->prepare_for_position();
h2->extra(HA_EXTRA_KEYREAD);
......@@ -404,7 +448,6 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
if (h2->ha_index_init(mrr_keyno, FALSE))
goto error;
use_default_impl= FALSE;
if (pushed_cond)
h2->idx_cond_push(mrr_keyno, pushed_cond);
}
......@@ -422,14 +465,13 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
h2= NULL;
int res= (h->inited == handler::INDEX && h->ha_index_end());
h2= save_h2;
use_default_impl= FALSE;
if (res)
goto error;
}
if (h2->handler::multi_range_read_init(seq_funcs, seq_init_param, n_ranges,
mode, buf) ||
dsmrr_fill_buffer())
dsmrr_fill_rowid_buffer())
{
goto error;
}
......@@ -449,7 +491,6 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
(h->ha_rnd_init(FALSE))))
goto error;
use_default_impl= FALSE;
h->mrr_funcs= *seq_funcs;
DBUG_RETURN(0);
......@@ -498,6 +539,9 @@ static int rowid_cmp(void *h, uchar *a, uchar *b)
dsmrr_eof is set to indicate whether we've exhausted the list of ranges we're
scanning.
psergey2: this func will 'fill the rowid buffer'. If filling the rowid buffer
requires that key buffer is filled/sorted first, will do that, too.
@param h Table handler
@retval 0 OK, the next portion of rowids is in the buffer,
......@@ -505,13 +549,27 @@ static int rowid_cmp(void *h, uchar *a, uchar *b)
@retval other Error
*/
int DsMrr_impl::dsmrr_fill_buffer()
int DsMrr_impl::dsmrr_fill_rowid_buffer()
{
char *range_info;
int res;
DBUG_ENTER("DsMrr_impl::dsmrr_fill_buffer");
DBUG_ENTER("DsMrr_impl::dsmrr_fill_rowid_buffer");
mrr_buf_cur= mrr_buf;
mrr_buf_next_identical= mrr_buf_cur;
/*
psergey2-todo:
- call here fill/sort key buffer, if needed.
psergey2-todo: then, get keys either from
- multi_range_read_next()
- sorted key buffer
psergey2-todo: if we're traversing an ordered key sequence,
check if next keys are the same as previous.
(note that it's easy as ordered sequence allows forward/backward
navigation so we don't need to buffer things)
*/
while ((mrr_buf_cur < mrr_buf_end) &&
!(res= h2->handler::multi_range_read_next(&range_info)))
{
......@@ -520,6 +578,7 @@ int DsMrr_impl::dsmrr_fill_buffer()
h2->mrr_funcs.skip_index_tuple(h2->mrr_iter, curr_range->ptr))
continue;
/* Put rowid, or {rowid, range_id} pair into the buffer */
h2->position(table->record[0]);
memcpy(mrr_buf_cur, h2->ref, h2->ref_length);
......@@ -579,20 +638,26 @@ int DsMrr_impl::key_tuple_cmp(void* arg, uchar* key1, uchar* key2)
DS-MRR/CPK: Fill the buffer with (lookup_tuple, range_id) pairs and sort
SYNOPSIS
DsMrr_impl::dsmrr_fill_buffer_cpk()
DsMrr_impl::dsmrr_fill_key_buffer()
DESCRIPTION
DS-MRR/CPK: Fill the buffer with (lookup_tuple, range_id) pairs and sort
dsmrr_eof is set to indicate whether we've exhausted the list of ranges
we're scanning.
psergey2-q: can this be used for filling/sorting key buffer in general case?
a: yes.
qq: can we push sequence iteration init down into here?
*/
void DsMrr_impl::dsmrr_fill_buffer_cpk()
void DsMrr_impl::dsmrr_fill_key_buffer()
{
//psergey2: here, no identicals detection is necessary since we always scan
// the unordered sequence.
int res;
KEY_MULTI_RANGE cur_range;
DBUG_ENTER("DsMrr_impl::dsmrr_fill_buffer_cpk");
DBUG_ENTER("DsMrr_impl::dsmrr_fill_key_buffer");
mrr_buf_cur= mrr_buf;
while ((mrr_buf_cur < mrr_buf_end) &&
......@@ -611,6 +676,8 @@ void DsMrr_impl::dsmrr_fill_buffer_cpk()
mrr_buf_end= mrr_buf_last;
}
//psergey2: if keys are materialized, store pointers, not copy keys
/* Put key, or {key, range_id} pair into the buffer */
memcpy(mrr_buf_cur, cur_range.start_key.key, cpk_tuple_length);
mrr_buf_cur += cpk_tuple_length;
......@@ -648,12 +715,14 @@ void DsMrr_impl::dsmrr_fill_buffer_cpk()
This is similar to DsMrr_impl::dsmrr_next(), the differences are that
- we get records with index_read(), not with rnd_pos()
- we may get multiple records for one key (=element of the buffer)
- unlike dsmrr_fill_buffer(), dsmrr_fill_buffer_cpk() never fails.
- unlike dsmrr_fill_rowid_buffer(), dsmrr_fill_key_buffer() never fails.
RETURN
0 OK, next record was successfully read
HA_ERR_END_OF_FILE End of records
Other Some other error
psergey2-todo: this should detect identical keys.
*/
int DsMrr_impl::dsmrr_next_cpk(char **range_info)
......@@ -697,7 +766,7 @@ int DsMrr_impl::dsmrr_next_cpk(char **range_info)
res= HA_ERR_END_OF_FILE;
goto end;
}
dsmrr_fill_buffer_cpk();
dsmrr_fill_key_buffer();
}
if (mrr_buf_cur == mrr_buf_last)
{
......@@ -758,6 +827,9 @@ end:
/**
DS-MRR implementation: multi_range_read_next() function
psergey2-todo: put identical rowid detection code here
it should always work because rowid sequences are always sorted
*/
int DsMrr_impl::dsmrr_next(char **range_info)
......@@ -772,6 +844,23 @@ int DsMrr_impl::dsmrr_next(char **range_info)
if (doing_cpk_scan)
return dsmrr_next_cpk(range_info);
if (mrr_buf_next_identical != mrr_buf_cur)
{
/*
There are multiple rowids. Return the record again, now with different
range_id
*/
do
{
if (is_mrr_assoc)
memcpy(range_info, mrr_buf_next_identical + h->ref_length, sizeof(uchar*));
} while (!h2->mrr_funcs.skip_record ||
!h2->mrr_funcs.skip_record(h2->mrr_iter, (char *) range_info, rowid));
mrr_buf_next_identical += h->ref_length + sizeof(void*) * test(is_mrr_assoc);
return 0;
}
do
{
if (mrr_buf_cur == mrr_buf_last)
......@@ -781,7 +870,7 @@ int DsMrr_impl::dsmrr_next(char **range_info)
res= HA_ERR_END_OF_FILE;
goto end;
}
res= dsmrr_fill_buffer();
res= dsmrr_fill_rowid_buffer();
if (res)
goto end;
}
......@@ -797,12 +886,33 @@ int DsMrr_impl::dsmrr_next(char **range_info)
if (is_mrr_assoc)
memcpy(&cur_range_info, mrr_buf_cur + h->ref_length, sizeof(uchar**));
mrr_buf_cur += h->ref_length + sizeof(void*) * test(is_mrr_assoc);
size_t element_size= h->ref_length + sizeof(void*) * test(is_mrr_assoc);
mrr_buf_cur += element_size;
mrr_buf_next_identical= mrr_buf_cur;
if (h2->mrr_funcs.skip_record &&
h2->mrr_funcs.skip_record(h2->mrr_iter, (char *) cur_range_info, rowid))
continue;
res= h->ha_rnd_pos(table->record[0], rowid);
if (res == HA_ERR_RECORD_DELETED)
continue;
if (0)//(!res)
{
/*
Note: this implies that SQL layer doesn't touch table->record[0]
between calls.
*/
uchar *current_el= mrr_buf_cur - element_size;
while (mrr_buf_cur != mrr_buf_last &&
!h2->cmp_ref(current_el, mrr_buf_cur))
{
mrr_buf_cur += element_size;
}
}
break;
} while (true);
if (is_mrr_assoc)
......@@ -1010,6 +1120,10 @@ bool DsMrr_impl::choose_mrr_impl(uint keyno, ha_rows rows, uint *flags,
*flags &= ~HA_MRR_SORTED; /* We will return unordered output */
*cost= dsmrr_cost;
res= FALSE;
if ((*flags & HA_MRR_SINGLE_POINT) &&
optimizer_flag(thd, OPTIMIZER_SWITCH_MRR_SORT_KEYS))
*flags |= HA_MRR_MATERIALIZED_KEYS;
}
else
{
......
......@@ -114,6 +114,8 @@ private:
uchar *mrr_buf_last; /* When reading: end of used buffer space */
uchar *mrr_buf_end; /* End of the buffer */
uchar *mrr_buf_next_identical;
bool dsmrr_eof; /* TRUE <=> We have reached EOF when reading index tuples */
/* TRUE <=> need range association, buffer holds {rowid, range_id} pairs */
......@@ -143,8 +145,8 @@ private:
uint *buffer_size, COST_VECT *cost);
bool check_cpk_scan(uint keyno, uint mrr_flags);
static int key_tuple_cmp(void* arg, uchar* key1, uchar* key2);
int dsmrr_fill_buffer();
void dsmrr_fill_buffer_cpk();
int dsmrr_fill_rowid_buffer();
void dsmrr_fill_key_buffer();
int dsmrr_next_cpk(char **range_info);
};
......@@ -571,12 +571,13 @@ protected:
#define OPTIMIZER_SWITCH_PARTIAL_MATCH_ROWID_MERGE 512
#define OPTIMIZER_SWITCH_PARTIAL_MATCH_TABLE_SCAN 1024
#define OPTIMIZER_SWITCH_SUBQUERY_CACHE (1<<11)
#define OPTIMIZER_SWITCH_MRR_SORT_KEYS (1<<12)
#ifdef DBUG_OFF
# define OPTIMIZER_SWITCH_LAST (1<<12)
#else
# define OPTIMIZER_SWITCH_TABLE_ELIMINATION (1<<12)
# define OPTIMIZER_SWITCH_LAST (1<<13)
#else
# define OPTIMIZER_SWITCH_TABLE_ELIMINATION (1<<13)
# define OPTIMIZER_SWITCH_LAST (1<<14)
#endif
#ifdef DBUG_OFF
......@@ -592,7 +593,8 @@ protected:
OPTIMIZER_SWITCH_SEMIJOIN | \
OPTIMIZER_SWITCH_PARTIAL_MATCH_ROWID_MERGE|\
OPTIMIZER_SWITCH_PARTIAL_MATCH_TABLE_SCAN|\
OPTIMIZER_SWITCH_SUBQUERY_CACHE)
OPTIMIZER_SWITCH_SUBQUERY_CACHE|\
OPTIMIZER_SWITCH_MRR_SORT_KEYS)
#else
# define OPTIMIZER_SWITCH_DEFAULT (OPTIMIZER_SWITCH_INDEX_MERGE | \
OPTIMIZER_SWITCH_INDEX_MERGE_UNION | \
......@@ -606,7 +608,8 @@ protected:
OPTIMIZER_SWITCH_SEMIJOIN | \
OPTIMIZER_SWITCH_PARTIAL_MATCH_ROWID_MERGE|\
OPTIMIZER_SWITCH_PARTIAL_MATCH_TABLE_SCAN|\
OPTIMIZER_SWITCH_SUBQUERY_CACHE)
OPTIMIZER_SWITCH_SUBQUERY_CACHE|\
OPTIMIZER_SWITCH_MRR_SORT_KEYS)
#endif
/*
......
......@@ -308,6 +308,7 @@ static const char *optimizer_switch_names[]=
"partial_match_rowid_merge",
"partial_match_table_scan",
"subquery_cache",
"mrr_sort_keys",
#ifndef DBUG_OFF
"table_elimination",
#endif
......@@ -329,6 +330,7 @@ static const unsigned int optimizer_switch_names_len[]=
sizeof("partial_match_rowid_merge") - 1,
sizeof("partial_match_table_scan") - 1,
sizeof("subquery_cache") - 1,
sizeof("mrr_sort_keys") - 1,
#ifndef DBUG_OFF
sizeof("table_elimination") - 1,
#endif
......@@ -415,7 +417,8 @@ static const char *optimizer_switch_str="index_merge=on,index_merge_union=on,"
"semijoin=on,"
"partial_match_rowid_merge=on,"
"partial_match_table_scan=on,"
"subquery_cache=on"
"subquery_cache=on,"
"mrr_sort_keys=on"
#ifndef DBUG_OFF
",table_elimination=on";
#else
......
......@@ -651,6 +651,9 @@ int JOIN_CACHE_BKA::init()
use_emb_key= check_emb_key_usage();
if (use_emb_key)
mrr_mode|= HA_MRR_MATERIALIZED_KEYS;
create_remaining_fields(FALSE);
set_constants();
......@@ -2631,6 +2634,8 @@ int JOIN_CACHE_BKA_UNIQUE::init()
data_fields_offset+= copy->length;
}
mrr_mode|= HA_MRR_MATERIALIZED_KEYS;
DBUG_RETURN(rc);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment