summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorSergey Petrunya <psergey@askmonty.org>2010-11-08 20:37:01 +0300
committerSergey Petrunya <psergey@askmonty.org>2010-11-08 20:37:01 +0300
commit0fb342ba566c0fe65ec62593b7ef254ae53e44bd (patch)
treea501aa3f01e98ce14f7a7d4d4e5d605e0173bb64 /sql
parent197c99427dc0119c6d24072faefaeb614a02e350 (diff)
downloadmariadb-git-0fb342ba566c0fe65ec62593b7ef254ae53e44bd.tar.gz
BUG#670417: Diverging results in maria-5.3-mwl128-dsmrr-cpk with join buffer, attempt 4
- Disable identical key handling optimization when IndexConditionPushdown is used
Diffstat (limited to 'sql')
-rw-r--r--sql/multi_range_read.cc39
-rw-r--r--sql/multi_range_read.h6
2 files changed, 44 insertions, 1 deletions
diff --git a/sql/multi_range_read.cc b/sql/multi_range_read.cc
index dcb90b294a5..234a5fdaa2f 100644
--- a/sql/multi_range_read.cc
+++ b/sql/multi_range_read.cc
@@ -472,6 +472,42 @@ int Mrr_ordered_index_reader::init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
mrr_funcs= *seq_funcs;
know_key_tuple_params= FALSE;
buf_manager= buf_manager_arg;
+ /*
+ Short: don't do identical key handling when we have a pushed index
+ condition.
+
+ Long: In order to check pushed index condition, we need to have both
+ index tuple table->record[0] and range_id.
+
+ Key_value_records_iterator has special handling for case when we have
+ multiple (key_value, range_id) pairs with the same key_value. In that
+ case it will make an index lookup only for the first such element,
+ for subsequent elements it will only return the new range_id.
+
+ The problem here is that h->table->record[0] is shared with the part that
+ does full record retrieval with rnd_pos() calls, and if we have the
+ following scenario:
+
+ 1. We scan ranges {(key_value, range_id1), (key_value, range_id2)}
+ 2. Iterator makes a lookup with key_value, produces the (index_tuple,
+ range_id1) pair. Index tuple is read into table->record[0], which
+ allows us to check index condition.
+ 3. At this point, we figure that key buffer is full, so we sort it,
+ and return control to Mrr_ordered_rndpos_reader.
+ 3.1 Mrr_ordered_rndpos_reader gets rowids and makes rnd_pos() calls, which
+ puts some arbitrary data into table->record[0] in the process.
+ 3.2 We ask the iterator for the next (rowid, range_id) pair. The iterator
+ puts in range_id2, and that shuld be sufficient (this is identical key
+ handling at work)
+ However, index tuple in table->record[0] has been destroyed and we
+ can't check index conditon for (index_tuple, range_id2) now.
+
+ TODO: It is possible to support identical key handling and index condition
+ pushdown, working together (one possible solution is to save/restore the
+ contents of table->record[0]). We will probably implement that.
+
+ */
+ disallow_identical_key_handling= test(mrr_funcs.skip_index_tuple);
return 0;
}
@@ -1123,7 +1159,8 @@ int Key_value_records_iterator::init(Mrr_ordered_index_reader *owner_arg)
uchar *save_cur_index_tuple= cur_index_tuple;
while (!identical_key_it.read())
{
- if (Mrr_ordered_index_reader::key_tuple_cmp(owner, key_in_buf,
+ if (owner->disallow_identical_key_handling ||
+ Mrr_ordered_index_reader::key_tuple_cmp(owner, key_in_buf,
cur_index_tuple))
break;
last_identical_key_ptr= cur_index_tuple;
diff --git a/sql/multi_range_read.h b/sql/multi_range_read.h
index b945cc21b25..8e2743df5f1 100644
--- a/sql/multi_range_read.h
+++ b/sql/multi_range_read.h
@@ -289,6 +289,12 @@ private:
/* TRUE <=> need range association, buffers hold {rowid, range_id} pairs */
bool is_mrr_assoc;
+ /*
+ TRUE <=> Don't do optimizations for identical key value (see comment in
+ Mrr_ordered_index_reader::init for details)
+ */
+ bool disallow_identical_key_handling;
+
/* Range sequence iteration members */
RANGE_SEQ_IF mrr_funcs;
range_seq_t mrr_iter;