-
Notifications
You must be signed in to change notification settings - Fork 713
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Summary: In current bypass implementation, its range query implementation is not correct. For A >= begin and A <= end , it'll only pick begin *or* end as start of the range, but it will only use the prefix as the end of the range, which means it can potentially scan a lot more rows than needed. It rely on the condition A >= begin / A <= end to filter out the unnecessary rows so the end result is correct (that's why this issue is not discovered in testing). The correct way to implement is to set up (begin, end) range slice correctly, and do NOT rely on any conditional evaluation to filter rows. The tricky part is to determine the correct begin/end based on a few factors: * forward / reverse column family * ascending / descending orders * inclusive vs non-inclusive ranges (>=, <= vs <, >) * prefix query vs range query For better testing, I've done the following: * verify_bypass_query.inc that will run the query in bypass and non-bypass, verify the row reads are same or less than non-bypass case to ensure such issue won't happen again. Most bypass query validation are moved to use verify_bypass_query.inc. We can also add more validation in the future in verify_bypass_query.inc as needed. As a bonus, it'll make verifying the results are the same in bypass/non-bypass case easy as well. * move range key validation from bypass_select_scenarios into bypass_select_range_pk and bypass_select_range_sk * added more test cases to bypass_select_range_pk / bypass_select_range_sk, especially for PK case where some scenarios are missing * dump query results to file and verify query results didn't change w/ and w/o bypass. I had to back port `output` mysqltest support to make this work properly (for some reason --exec $MYSQL doesn't like multiline queries". For review, there is no need to go through results file as there are validation in-place to make sure query return same results w/ and w/o bypass. Reviewed By: luqun Differential Revision: D25982322 fbshipit-source-id: c857f9a382e
- Loading branch information
1 parent
5eba6ba
commit ef9a677
Showing
24 changed files
with
25,839 additions
and
7,032 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
101 changes: 101 additions & 0 deletions
101
mysql-test/suite/rocksdb/include/verify_bypass_query.inc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
# Run bypass query and print rows being read | ||
# This is needed to make sure bypass query read exactly the right amount of | ||
# rows and avoid performance regression | ||
# | ||
# Parameters | ||
# $bypass_query | ||
# Bypass query to run | ||
|
||
--disable_query_log | ||
SELECT @@rocksdb_select_bypass_policy INTO @__rocksdb_select_bypass_policy; | ||
SET GLOBAL rocksdb_select_bypass_policy=2; | ||
|
||
SELECT variable_value INTO @bypass_rows_read_0 FROM | ||
information_schema.global_status WHERE | ||
variable_name="rocksdb_rows_read"; | ||
SELECT variable_value INTO @bypass_rows_sent_0 FROM | ||
information_schema.global_status WHERE | ||
variable_name="rows_sent"; | ||
SELECT variable_value INTO @bypass_executed_0 FROM | ||
information_schema.global_status WHERE | ||
variable_name="rocksdb_select_bypass_executed"; | ||
|
||
--echo ========== Verifying Bypass Query ========== | ||
--echo WITH BYPASS: | ||
|
||
--enable_query_log | ||
--output $MYSQL_TMP_DIR/bypass_query_rows | ||
--eval $bypass_query | ||
--disable_query_log | ||
--cat_file $MYSQL_TMP_DIR/bypass_query_rows | ||
|
||
SELECT variable_value INTO @bypass_rows_read_1 FROM | ||
information_schema.global_status WHERE | ||
variable_name="rocksdb_rows_read"; | ||
SELECT variable_value INTO @bypass_rows_sent_1 FROM | ||
information_schema.global_status WHERE | ||
variable_name="rows_sent"; | ||
SELECT variable_value INTO @bypass_executed_1 FROM | ||
information_schema.global_status WHERE | ||
variable_name="rocksdb_select_bypass_executed"; | ||
|
||
--let rows_read_bypass=`SELECT @bypass_rows_read_1 - @bypass_rows_read_0` | ||
SELECT @bypass_rows_read_1 - @bypass_rows_read_0 AS ROWS_READ; | ||
|
||
--let $assert_cond= @bypass_executed_1 - @bypass_executed_0 = 1 | ||
--let $assert_text = Verify executed in bypass | ||
--source include/assert.inc | ||
|
||
SELECT variable_value INTO @bypass_rows_read_2 FROM | ||
information_schema.global_status WHERE | ||
variable_name="rocksdb_rows_read"; | ||
SELECT variable_value INTO @bypass_rows_sent_2 FROM | ||
information_schema.global_status WHERE | ||
variable_name="rows_sent"; | ||
SELECT variable_value INTO @bypass_executed_2 FROM | ||
information_schema.global_status WHERE | ||
variable_name="rocksdb_select_bypass_executed"; | ||
|
||
--echo WITHOUT BYPASS: | ||
SET GLOBAL rocksdb_select_bypass_policy=0; | ||
|
||
--enable_query_log | ||
--output $MYSQL_TMP_DIR/regular_query_rows | ||
--eval $bypass_query | ||
--disable_query_log | ||
--cat_file $MYSQL_TMP_DIR/regular_query_rows | ||
|
||
--diff_files $MYSQL_TMP_DIR/bypass_query_rows $MYSQL_TMP_DIR/regular_query_rows | ||
--remove_file $MYSQL_TMP_DIR/bypass_query_rows | ||
--remove_file $MYSQL_TMP_DIR/regular_query_rows | ||
|
||
SELECT variable_value INTO @bypass_rows_read_3 FROM | ||
information_schema.global_status WHERE | ||
variable_name="rocksdb_rows_read"; | ||
SELECT variable_value INTO @bypass_rows_sent_3 FROM | ||
information_schema.global_status WHERE | ||
variable_name="rows_sent"; | ||
SELECT variable_value INTO @bypass_executed_3 FROM | ||
information_schema.global_status WHERE | ||
variable_name="rocksdb_select_bypass_executed"; | ||
|
||
--let $assert_cond= @bypass_executed_3 - @bypass_executed_2 = 0 | ||
--let $assert_text = Verify not executed in bypass | ||
--source include/assert.inc | ||
|
||
--let rows_read_no_bypass=`SELECT @bypass_rows_read_3 - @bypass_rows_read_2` | ||
# This doesn't seem to be stable outside bypass | ||
# SELECT @bypass_rows_read_3 - @bypass_rows_read_2 AS ROWS_READ; | ||
|
||
SET GLOBAL rocksdb_select_bypass_policy=@__rocksdb_select_bypass_policy; | ||
|
||
let $assert_cond= @bypass_rows_sent_3 - @bypass_rows_sent_2 = | ||
@bypass_rows_sent_1 - @bypass_rows_sent_0; | ||
--let $assert_text = Verify bypass and regular query return same number of rows | ||
--source include/assert.inc | ||
|
||
--let $assert_cond= $ROWS_READ_BYPASS <= $ROWS_READ_NO_BYPASS; | ||
--let $assert_text = Verify bypass reads no more than regular query | ||
--source include/assert.inc | ||
|
||
--enable_query_log |
Oops, something went wrong.