mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
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
This commit is contained in:
@ -462,3 +462,48 @@ FROM t1
|
|||||||
WHERE `key1` LIKE CONCAT( LEFT( '1' , 7 ) , '%' )
|
WHERE `key1` LIKE CONCAT( LEFT( '1' , 7 ) , '%' )
|
||||||
ORDER BY col1 LIMIT 7;
|
ORDER BY col1 LIMIT 7;
|
||||||
drop table t0, t1, t2;
|
drop table t0, t1, t2;
|
||||||
|
#
|
||||||
|
# BUG#670417: Diverging results in maria-5.3-mwl128-dsmrr-cpk with join buffer (incremental, BKA join)
|
||||||
|
#
|
||||||
|
set @save_join_cache_level = @@join_cache_level;
|
||||||
|
set join_cache_level = 6;
|
||||||
|
set @save_join_buffer_size=@@join_buffer_size;
|
||||||
|
set join_buffer_size = 136;
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
pk int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
col_int_key int(11) NOT NULL,
|
||||||
|
col_varchar_key varchar(1) NOT NULL,
|
||||||
|
col_varchar_nokey varchar(1) NOT NULL,
|
||||||
|
PRIMARY KEY (pk),
|
||||||
|
KEY col_varchar_key (col_varchar_key,col_int_key)
|
||||||
|
);
|
||||||
|
INSERT INTO t1 VALUES
|
||||||
|
(10,8,'v','v'),(11,8,'f','f'), (12,5,'v','v'),
|
||||||
|
(13,8,'s','s'),(14,8,'a','a'),(15,6,'p','p'),
|
||||||
|
(16,7,'z','z'),(17,2,'a','a'),(18,5,'h','h'),
|
||||||
|
(19,7,'h','h'),(20,2,'v','v'),(21,9,'v','v'),
|
||||||
|
(22,142,'b','b'),(23,3,'y','y'),(24,0,'v','v'),
|
||||||
|
(25,3,'m','m'),(26,5,'z','z'),(27,9,'n','n'),
|
||||||
|
(28,1,'d','d'),(29,107,'a','a');
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM
|
||||||
|
t1 AS table2, t1 AS table3
|
||||||
|
where
|
||||||
|
table3.col_varchar_key = table2.col_varchar_key AND
|
||||||
|
table3.col_varchar_key = table2.col_varchar_nokey AND
|
||||||
|
table3.pk<>0;
|
||||||
|
COUNT(*)
|
||||||
|
50
|
||||||
|
EXPLAIN SELECT COUNT(*)
|
||||||
|
FROM
|
||||||
|
t1 AS table2, t1 AS table3
|
||||||
|
where
|
||||||
|
table3.col_varchar_key = table2.col_varchar_key AND
|
||||||
|
table3.col_varchar_key = table2.col_varchar_nokey AND
|
||||||
|
table3.pk<>0;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE table2 ALL col_varchar_key NULL NULL NULL 20 Using where
|
||||||
|
1 SIMPLE table3 ref PRIMARY,col_varchar_key col_varchar_key 3 test.table2.col_varchar_key 3 Using index condition(BKA); Using where; Using join buffer (flat, BKA join)
|
||||||
|
set join_cache_level= @save_join_cache_level;
|
||||||
|
set join_buffer_size= @save_join_buffer_size;
|
||||||
|
drop table t1;
|
||||||
|
@ -169,3 +169,52 @@ FROM t1
|
|||||||
WHERE `key1` LIKE CONCAT( LEFT( '1' , 7 ) , '%' )
|
WHERE `key1` LIKE CONCAT( LEFT( '1' , 7 ) , '%' )
|
||||||
ORDER BY col1 LIMIT 7;
|
ORDER BY col1 LIMIT 7;
|
||||||
drop table t0, t1, t2;
|
drop table t0, t1, t2;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # BUG#670417: Diverging results in maria-5.3-mwl128-dsmrr-cpk with join buffer (incremental, BKA join)
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
set @save_join_cache_level = @@join_cache_level;
|
||||||
|
set join_cache_level = 6;
|
||||||
|
set @save_join_buffer_size=@@join_buffer_size;
|
||||||
|
--disable_warnings
|
||||||
|
set join_buffer_size = 136;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
pk int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
col_int_key int(11) NOT NULL,
|
||||||
|
col_varchar_key varchar(1) NOT NULL,
|
||||||
|
col_varchar_nokey varchar(1) NOT NULL,
|
||||||
|
PRIMARY KEY (pk),
|
||||||
|
KEY col_varchar_key (col_varchar_key,col_int_key)
|
||||||
|
);
|
||||||
|
INSERT INTO t1 VALUES
|
||||||
|
(10,8,'v','v'),(11,8,'f','f'), (12,5,'v','v'),
|
||||||
|
(13,8,'s','s'),(14,8,'a','a'),(15,6,'p','p'),
|
||||||
|
(16,7,'z','z'),(17,2,'a','a'),(18,5,'h','h'),
|
||||||
|
(19,7,'h','h'),(20,2,'v','v'),(21,9,'v','v'),
|
||||||
|
(22,142,'b','b'),(23,3,'y','y'),(24,0,'v','v'),
|
||||||
|
(25,3,'m','m'),(26,5,'z','z'),(27,9,'n','n'),
|
||||||
|
(28,1,'d','d'),(29,107,'a','a');
|
||||||
|
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM
|
||||||
|
t1 AS table2, t1 AS table3
|
||||||
|
where
|
||||||
|
table3.col_varchar_key = table2.col_varchar_key AND
|
||||||
|
table3.col_varchar_key = table2.col_varchar_nokey AND
|
||||||
|
table3.pk<>0;
|
||||||
|
|
||||||
|
EXPLAIN SELECT COUNT(*)
|
||||||
|
FROM
|
||||||
|
t1 AS table2, t1 AS table3
|
||||||
|
where
|
||||||
|
table3.col_varchar_key = table2.col_varchar_key AND
|
||||||
|
table3.col_varchar_key = table2.col_varchar_nokey AND
|
||||||
|
table3.pk<>0;
|
||||||
|
|
||||||
|
set join_cache_level= @save_join_cache_level;
|
||||||
|
set join_buffer_size= @save_join_buffer_size;
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
@ -472,6 +472,42 @@ int Mrr_ordered_index_reader::init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
|
|||||||
mrr_funcs= *seq_funcs;
|
mrr_funcs= *seq_funcs;
|
||||||
know_key_tuple_params= FALSE;
|
know_key_tuple_params= FALSE;
|
||||||
buf_manager= buf_manager_arg;
|
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;
|
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;
|
uchar *save_cur_index_tuple= cur_index_tuple;
|
||||||
while (!identical_key_it.read())
|
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))
|
cur_index_tuple))
|
||||||
break;
|
break;
|
||||||
last_identical_key_ptr= cur_index_tuple;
|
last_identical_key_ptr= cur_index_tuple;
|
||||||
|
@ -289,6 +289,12 @@ private:
|
|||||||
/* TRUE <=> need range association, buffers hold {rowid, range_id} pairs */
|
/* TRUE <=> need range association, buffers hold {rowid, range_id} pairs */
|
||||||
bool is_mrr_assoc;
|
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 sequence iteration members */
|
||||||
RANGE_SEQ_IF mrr_funcs;
|
RANGE_SEQ_IF mrr_funcs;
|
||||||
range_seq_t mrr_iter;
|
range_seq_t mrr_iter;
|
||||||
|
Reference in New Issue
Block a user