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) [non-RocksDB part]

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

Pulled By: yoshinorim
  • Loading branch information
yoshinorim authored and inikep committed Jun 6, 2024
1 parent 5e6d4dd commit 82a4801
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 2 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 @@ -154,16 +154,22 @@ analyze table t2;
-- enable_result_log
-- enable_query_log

if (!$skip_ror_EXPLAIN_for_MyRocks)
{
--replace_regex $elide_costs
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)
{
--replace_regex $elide_costs
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,9 +384,12 @@ analyze table t1;
-- enable_result_log
-- enable_query_log

if (!$skip_ror_EXPLAIN_for_MyRocks)
{
# to test the bug, the following must use "sort_union":
--replace_regex $elide_costs
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
55 changes: 53 additions & 2 deletions mysql-test/include/index_merge_ror.inc
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ analyze table t1;
--replace_regex $elide_costs_and_rows
explain select key1,key2 from t1 where key1=100 and key2=100;
select key1,key2 from t1 where key1=100 and key2=100;
if (!$skip_ror_EXPLAIN_for_MyRocks)
{
--replace_result key2 key1 key4 key3
--replace_regex $elide_costs_and_rows
explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
Expand All @@ -141,6 +143,8 @@ explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 o
--replace_result key2 key1 key4 key3
--replace_regex /(_rows": )[0-9.]+/\1"#"/ /(_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 @@ -154,38 +158,57 @@ analyze table t1;
-- enable_query_log

--echo # ROR-intersection, not covering
if (!$skip_ror_EXPLAIN_for_MyRocks)
{

--replace_result key2 key1
--replace_regex $elide_costs_and_rows
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
if (!$skip_ror_EXPLAIN_for_MyRocks)
{
--replace_result key2 key1
--replace_regex $elide_costs_and_rows
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)
{
--replace_result key2 key1 key4 key3
--replace_regex $elide_costs_and_rows
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;
if (!$skip_ror_EXPLAIN_for_MyRocks)
{
--replace_result key2 key1 key4 key3
--replace_regex $elide_costs_and_rows
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
if (!$skip_ror_EXPLAIN_for_MyRocks)
{
--replace_result key2 key1 key3 key1
--replace_regex $elide_costs_and_rows
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');
if (!$skip_ror_EXPLAIN_for_MyRocks)
{
--replace_result key2 key1
--replace_regex $elide_costs_and_rows
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 @@ -202,9 +225,12 @@ 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
if (!$skip_ror_EXPLAIN_for_MyRocks)
{
--replace_result key2 key1 key4 key3
--replace_regex $elide_costs_and_rows
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 @@ -218,15 +244,21 @@ 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
if (!$skip_ror_EXPLAIN_for_MyRocks)
{
--replace_result key2 key1 key4 key3
--replace_regex $elide_costs_and_rows
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
if (!$skip_ror_EXPLAIN_for_MyRocks)
{
--replace_result key2 key1 key4 key3
--replace_regex $elide_costs_and_rows
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 @@ -241,9 +273,12 @@ analyze table t1;
-- enable_result_log
-- enable_query_log

if (!$skip_ror_EXPLAIN_for_MyRocks)
{
--replace_result key2 key1 key4 key3
--replace_regex $elide_costs_and_rows
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 @@ -254,9 +289,12 @@ analyze table t1;
-- enable_result_log
-- enable_query_log

--replace_result key2 key1 key4 key3
if (!$skip_ror_EXPLAIN_for_MyRocks)
{
--replace_result key2 key1 key4 key3
--replace_regex $elide_costs_and_rows
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 @@ -267,9 +305,12 @@ analyze table t1;
-- enable_result_log
-- enable_query_log

if (!$skip_ror_EXPLAIN_for_MyRocks)
{
--replace_result key2 key1 key4 key3
--replace_regex $elide_costs_and_rows
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 @@ -288,12 +329,21 @@ if ($engine_type != "InnoDB" )
--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_regex $elide_costs_and_rows
--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 #
}
--replace_regex $elide_costs_and_rows
explain select * from t1 where st_b=1 and swt1b=1 and swt2b=1;

Expand Down Expand Up @@ -327,6 +377,7 @@ explain select st_a from t1
--replace_regex $elide_costs_and_rows
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

0 comments on commit 82a4801

Please sign in to comment.