Skip to content

Commit

Permalink
Fixing index_merge query returning wrong results (facebook#624) (face…
Browse files Browse the repository at this point in the history
…book#626) (facebook#626)

Summary:
This diff fixed MyRocks returning missing rows if index
merge query plan was used. When index merge is selected,
table->read_map is cleared at
QUICK_RANGE_SELECT::init_ror_merged_scan(). Then
ha_rocksdb::setup_read_decoders() wrongly decided not to decode
all fields, which made MySQL layer decide that keys did not match.
This diff changes ha_rocksdb::setup_read_decoders() to
always decode if read_map is cleared. A side effect is decoding
all fetched fields on index merge. There is a slight performance
penalty but much better than returning wrong results.

This diff reuses index_merge_ror.inc and index_merge_2sweeps.inc
test cases for MyRocks. Since MyRocks query plan is less stable than
InnoDB, it skips using explain and just verifies data correctness.
Closes facebook#626

Differential Revision: D5088547 (facebook@3b2cc9f)

Pulled By: yoshinorim

fbshipit-source-id: 9f0aee0da20
  • Loading branch information
yoshinorim authored and inikep committed Aug 17, 2021
1 parent 9bd2712 commit c36b58e
Show file tree
Hide file tree
Showing 9 changed files with 1,618 additions and 20 deletions.
9 changes: 9 additions & 0 deletions mysql-test/include/index_merge2.inc
Original file line number Diff line number Diff line change
Expand Up @@ -148,22 +148,28 @@ analyze table t2;
-- enable_result_log
-- enable_query_log

if (!$skip_ror_EXPLAIN_for_MyRocks)
{
if ($index_merge_random_rows_in_EXPLAIN)
{
--replace_column 10 #
}
explain select count(*) from t1 where
key1a = 2 and key1b is null and key2a = 2 and key2b is null;
}

select count(*) from t1 where
key1a = 2 and key1b is null and key2a = 2 and key2b is null;

if (!$skip_ror_EXPLAIN_for_MyRocks)
{
if ($index_merge_random_rows_in_EXPLAIN)
{
--replace_column 10 #
}
explain select count(*) from t1 where
key1a = 2 and key1b is null and key3a = 2 and key3b is null;
}

select count(*) from t1 where
key1a = 2 and key1b is null and key3a = 2 and key3b is null;
Expand Down Expand Up @@ -378,12 +384,15 @@ analyze table t1;
-- enable_result_log
-- enable_query_log

if (!$skip_ror_EXPLAIN_for_MyRocks)
{
if ($index_merge_random_rows_in_EXPLAIN)
{
--replace_column 10 #
}
# to test the bug, the following must use "sort_union":
explain select * from t1 where (key3 > 30 and key3<35) or (key2 >32 and key2 < 40);
}
select * from t1 where (key3 > 30 and key3<35) or (key2 >32 and key2 < 40);
drop table t1;

Expand Down
1 change: 0 additions & 1 deletion mysql-test/include/index_merge_2sweeps.inc
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ select * from t1 where
(pk < 5) or (pk > 10 and pk < 15) or (pk >= 50 and pk < 55 ) or (pk > @maxv-10)
or key1=18 or key1=60;

--sorted_result
select * from t1 where
(pk < 5) or (pk > 10 and pk < 15) or (pk >= 50 and pk < 55 ) or (pk > @maxv-10)
or key1 < 3 or key1 > @maxv-11;
Expand Down
89 changes: 70 additions & 19 deletions mysql-test/include/index_merge_ror.inc
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,16 @@ analyze table t1;
--echo # One row results tests for cases where a single row matches all conditions
explain select key1,key2 from t1 where key1=100 and key2=100;
select key1,key2 from t1 where key1=100 and key2=100;
explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
# Mask cost values since it varies between runs how much of the indexes
# are cached in InnoDB's buffer pool
--replace_regex /(_cost": )"[0-9.]+"/\1"#"/
explain format=json select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;

if (!$skip_ror_EXPLAIN_for_MyRocks)
{
explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
# Mask cost values since it varies between runs how much of the indexes
# are cached in InnoDB's buffer pool
--replace_regex /(_cost": )"[0-9.]+"/\1"#"/
explain format=json select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
}

select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;

--echo # Several-rows results
Expand All @@ -146,26 +151,44 @@ analyze table t1;
-- enable_query_log

--echo # ROR-intersection, not covering
explain select key1,key2,filler1 from t1 where key1=100 and key2=100;
if (!$skip_ror_EXPLAIN_for_MyRocks)
{
explain select key1,key2,filler1 from t1 where key1=100 and key2=100;
}
select key1,key2,filler1 from t1 where key1=100 and key2=100;

--echo # ROR-intersection, covering
explain select key1,key2 from t1 where key1=100 and key2=100;
if (!$skip_ror_EXPLAIN_for_MyRocks)
{
explain select key1,key2 from t1 where key1=100 and key2=100;
}
select key1,key2 from t1 where key1=100 and key2=100;

--echo # ROR-union of ROR-intersections
if (!$skip_ror_EXPLAIN_for_MyRocks)
{
explain select key1,key2,key3,key4 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
}
select key1,key2,key3,key4 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
if (!$skip_ror_EXPLAIN_for_MyRocks)
{
explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
}
select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;

--echo # 3-way ROR-intersection
explain select key1,key2,key3 from t1 where key1=100 and key2=100 and key3=100;
if (!$skip_ror_EXPLAIN_for_MyRocks)
{
explain select key1,key2,key3 from t1 where key1=100 and key2=100 and key3=100;
}
select key1,key2,key3 from t1 where key1=100 and key2=100 and key3=100;

--echo # ROR-union(ROR-intersection, ROR-range)
insert into t1 (key1,key2,key3,key4,filler1) values (101,101,101,101, 'key1234-101');
explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=101;
if (!$skip_ror_EXPLAIN_for_MyRocks)
{
explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=101;
}
select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=101;

--echo # Run some ROR updates/deletes
Expand All @@ -182,7 +205,10 @@ select key1,key2,filler1 from t1 where key2=100 and key2=200;

--echo # ROR-union(ROR-intersection) with one of ROR-intersection giving empty
--echo # results
explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
if (!$skip_ror_EXPLAIN_for_MyRocks)
{
explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
}
select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;

delete from t1 where key3=100 and key4=100;
Expand All @@ -196,12 +222,18 @@ analyze table t1;
--echo # ROR-union with all ROR-intersections giving empty results
# The relative order of keys inside
# "Using union(intersect(keyx,keyx),...)" doesn't matter
--replace_result key2,key1 key1,key2 key4,key3 key3,key4
explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
if (!$skip_ror_EXPLAIN_for_MyRocks)
{
--replace_result key2,key1 key1,key2 key4,key3 key3,key4
explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
}

--echo # ROR-intersection with empty result
explain select key1,key2 from t1 where key1=100 and key2=100;
if (!$skip_ror_EXPLAIN_for_MyRocks)
{
explain select key1,key2 from t1 where key1=100 and key2=100;
}
select key1,key2 from t1 where key1=100 and key2=100;

--echo # ROR-union tests with various cases.
Expand All @@ -216,7 +248,10 @@ analyze table t1;
-- enable_result_log
-- enable_query_log

explain select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200;
if (!$skip_ror_EXPLAIN_for_MyRocks)
{
explain select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200;
}
select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200;

insert into t1 (key1, key2, key3, key4, filler1) values (-1, -1, -1, 200,'key4');
Expand All @@ -227,7 +262,10 @@ analyze table t1;
-- enable_result_log
-- enable_query_log

explain select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200;
if (!$skip_ror_EXPLAIN_for_MyRocks)
{
explain select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200;
}
select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200;

insert into t1 (key1, key2, key3, key4, filler1) values (-1, -1, 200, -1,'key3');
Expand All @@ -238,7 +276,10 @@ analyze table t1;
-- enable_result_log
-- enable_query_log

explain select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200;
if (!$skip_ror_EXPLAIN_for_MyRocks)
{
explain select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200;
}
select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200;

--echo ##
Expand All @@ -257,11 +298,20 @@ if (!$index_merge_random_rows_in_EXPLAIN)
--echo # Do many tests
--echo # Check that keys that don't improve selectivity are skipped.
#

if (!$skip_ror_EXPLAIN_for_MyRocks)
{
# Different value on 32 and 64 bit
if ($random_rows_in_EXPLAIN)
{
--replace_column 9 #
}
--replace_result sta_swt12a sta_swt21a sta_swt12a, sta_swt12a,
explain select * from t1 where st_a=1 and swt1a=1 and swt2a=1;

if ($random_rows_in_EXPLAIN)
{
--replace_column 9 #
}
explain select * from t1 where st_b=1 and swt1b=1 and swt2b=1;

if ($index_merge_random_rows_in_EXPLAIN)
Expand Down Expand Up @@ -318,6 +368,7 @@ if ($index_merge_random_rows_in_EXPLAIN)
}
explain select st_a from t1
where st_a=1 and swt1a=1 and st_b=1 and swt1b=1 and swt1b=1;
}

drop table t0,t1;

Expand Down
23 changes: 23 additions & 0 deletions mysql-test/suite/rocksdb/r/index_merge_rocksdb.result
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,26 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge key1,key2 key1,key2 5,5 NULL # Using intersect(key1,key2); Using where
UPDATE t1 SET filler1='to be deleted' WHERE key1=100 and key2=100;
DROP TABLE t0, t1;
create table t1 (key1 int, key2 int, key3 int, key (key1), key (key2), key(key3)) engine=rocksdb;
insert into t1 values (1, 100, 100), (1, 200, 200), (1, 300, 300);
analyze table t1;
Table Op Msg_type Msg_text
test.t1 analyze status OK
set global rocksdb_force_flush_memtable_now=1;
explain select * from t1 where key1 = 1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref key1 key1 5 const # NULL
explain select key1,key2 from t1 where key1 = 1 or key2 = 1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge key1,key2 key1,key2 5,5 NULL # Using union(key1,key2); Using where
select * from t1 where key1 = 1;
key1 key2 key3
1 100 100
1 200 200
1 300 300
select key1,key2 from t1 where key1 = 1 or key2 = 1;
key1 key2
1 100
1 200
1 300
drop table t1;

0 comments on commit c36b58e

Please sign in to comment.