Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 19 additions & 5 deletions mysql-test/main/partition_index_scan,desc.rdiff
Original file line number Diff line number Diff line change
Expand Up @@ -287,8 +287,8 @@
show status like 'handler_read_%';
Variable_name Value
Handler_read_first 0
-Handler_read_key 6
+Handler_read_key 7
-Handler_read_key 8
+Handler_read_key 11
Handler_read_last 0
Handler_read_next 0
Handler_read_prev 0
Expand All @@ -301,9 +301,12 @@
) PARTITION BY RANGE COLUMNS(d) (
PARTITION `p1` VALUES LESS THAN (10),
PARTITION `p2` VALUES LESS THAN (20),
@@ -688,8 +688,8 @@
@@ -686,10 +686,10 @@
show status like 'handler_read_%';
Variable_name Value
Handler_read_first 0
Handler_read_key 1
-Handler_read_key 1
+Handler_read_key 2
Handler_read_last 0
-Handler_read_next 2
-Handler_read_prev 0
Expand All @@ -312,6 +315,15 @@
Handler_read_retry 0
Handler_read_rnd 0
Handler_read_rnd_deleted 0
@@ -698,7 +698,7 @@
set @js='$out';
select json_extract(@js,'$**.partitions_index_scan_method');
json_extract(@js,'$**.partitions_index_scan_method')
-["iterate_over_partitions"]
+["merge_ordered_scans"]
## Case 2: Unordered scans in ha_partition::index_read_map
flush status;
select * from t1 where c = 120 ORDER BY d DESC LIMIT 1;
@@ -725,8 +725,8 @@
Handler_read_first 0
Handler_read_key 1
Expand Down Expand Up @@ -479,7 +491,7 @@
Handler_read_prev 0
Handler_read_retry 0
Handler_read_rnd 0
@@ -1202,18 +1202,18 @@
@@ -1202,20 +1202,20 @@
#
# MDEV-40479: Reverse prefix scan across partitions
#
Expand All @@ -503,3 +515,5 @@
+11
+15
DROP TABLE t1;
#
# MDEV-41366 Wrong result with Case 2 of non-merging partition index scan
235 changes: 230 additions & 5 deletions mysql-test/main/partition_index_scan.result
Original file line number Diff line number Diff line change
Expand Up @@ -630,8 +630,8 @@ select json_extract(@js,'$**.partitions_index_scan_method');
json_extract(@js,'$**.partitions_index_scan_method')
["iterate_over_partitions"]
DROP TABLE t1;
## Case 2: calls to ha_partition::read_range_first and
## ha_partition::index_read_map, via loose index scan
## Case 2 loose index scan: calls to read_range_first iterates;
## index_read_map with AFTER_KEY is merged
CREATE TABLE t1 (
a INT,
b INT,
Expand All @@ -651,7 +651,7 @@ a MIN(b)
show status like 'handler_read_%';
Variable_name Value
Handler_read_first 0
Handler_read_key 6
Handler_read_key 8
Handler_read_last 0
Handler_read_next 0
Handler_read_prev 0
Expand All @@ -662,7 +662,7 @@ Handler_read_rnd_next 0
set @js='$out';
select json_extract(@js,'$**.partitions_index_scan_method');
json_extract(@js,'$**.partitions_index_scan_method')
["iterate_over_partitions"]
["both"]
DROP TABLE t1;
CREATE TABLE t1 (
c int,
Expand All @@ -676,7 +676,8 @@ PARTITION `p4` VALUES LESS THAN (40),
PARTITION `p5` VALUES LESS THAN MAXVALUE
);
insert into t1 select t2.seq, t3.seq from seq_100_to_200 t2, seq_1_to_50 t3;
## Case 2: Unordered scans with MRR
## Case 2: iterated partition scans with MRR with ASC key;
## merged scan with index_read_map with DESC key
flush status;
select * from t1 where c=113 and d between 25 and 35 order by d limit 3;
c d
Expand Down Expand Up @@ -1217,3 +1218,227 @@ c
11
6
DROP TABLE t1;
#
# MDEV-41366 Wrong result with Case 2 of non-merging partition index scan
#
# prefix-only PREFIX_LAST_OR_PREV, merged scan
CREATE TABLE t1 (a INT, b INT, c INT, PRIMARY KEY(a,c), KEY(b,c)) ENGINE=InnoDB
PARTITION BY RANGE(c) (PARTITION p0 VALUES LESS THAN (10),
PARTITION p1 VALUES LESS THAN (20));
INSERT INTO t1 VALUES (1,1,5),(2,0,12);
SELECT c FROM t1 FORCE INDEX(b) WHERE b=1 AND c<=15 ORDER BY c DESC;
c
5
set @js='$out';
select json_extract(@js,'$**.partitions_index_scan_method');
json_extract(@js,'$**.partitions_index_scan_method')
["merge_ordered_scans"]
DROP TABLE t1;
# same but with desc key
CREATE TABLE t1 (a INT, b INT, c INT, PRIMARY KEY(a,c), KEY(b desc,c desc)) ENGINE=InnoDB
PARTITION BY RANGE(c) (PARTITION p0 VALUES LESS THAN (10),
PARTITION p1 VALUES LESS THAN (20));
INSERT INTO t1 VALUES (1,1,5),(2,0,12);
SELECT c FROM t1 FORCE INDEX(b) WHERE b=0 AND c>=2 ORDER BY c;
c
12
set @js='$out';
select json_extract(@js,'$**.partitions_index_scan_method');
json_extract(@js,'$**.partitions_index_scan_method')
["merge_ordered_scans"]
DROP TABLE t1;
# prefix-only KEY_OR_NEXT / PREFIX_LAST_OR_PREV (opt_sum)
# merged scan
CREATE TABLE t1 (a INT, b INT, c INT NOT NULL, PRIMARY KEY(a,c), KEY k(b,c))
ENGINE=InnoDB
PARTITION BY RANGE(c) (PARTITION p0 VALUES LESS THAN (10),
PARTITION p1 VALUES LESS THAN (20),
PARTITION p2 VALUES LESS THAN (30));
# no b=1 in p0 or p2
INSERT INTO t1 VALUES (1,2,5),(2,1,15),(3,0,22);
EXPLAIN
SELECT MIN(c) FROM t1 WHERE b=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
FLUSH STATUS;
SELECT MIN(c) FROM t1 WHERE b=1;
MIN(c)
15
# 3 (merged scan: p0, p1, p2)
SHOW STATUS LIKE 'Handler_read_key';
Variable_name Value
Handler_read_key 3
EXPLAIN
SELECT MAX(c) FROM t1 WHERE b=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
FLUSH STATUS;
SELECT MAX(c) FROM t1 WHERE b=1;
MAX(c)
15
# 3 (merged scan: p0, p1, p2)
SHOW STATUS LIKE 'Handler_read_key';
Variable_name Value
Handler_read_key 3
DROP TABLE t1;
# index_first with prefix does not qualify Case 2
# neither does index_read_map with AFTER_KEY
CREATE TABLE t1 (a INT, b INT, KEY(a,b)) ENGINE=InnoDB
PARTITION BY RANGE COLUMNS(b) (PARTITION p1 VALUES LESS THAN (100),
PARTITION p2 VALUES LESS THAN (200),
PARTITION p3 VALUES LESS THAN MAXVALUE);
INSERT INTO t1 SELECT seq % 3 + 1, seq FROM seq_1_to_300;
ANALYZE TABLE t1 PERSISTENT FOR ALL;
Table Op Msg_type Msg_text
test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
EXPLAIN SELECT a, MIN(b) FROM t1 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range NULL a 10 NULL 4 Using index for group-by
SELECT a, MIN(b) FROM t1 GROUP BY a;
a MIN(b)
1 3
2 1
3 2
set @js='$out';
select json_extract(@js,'$**.partitions_index_scan_method');
json_extract(@js,'$**.partitions_index_scan_method')
["merge_ordered_scans"]
DROP TABLE t1;
# index_first with prefix does not qualify Case 2
# neither does index_read_map with AFTER_KEY
CREATE TABLE t1 (a INT, c INT, KEY(a,c)) ENGINE=InnoDB
PARTITION BY RANGE COLUMNS(c) (PARTITION p1 VALUES LESS THAN (100),
PARTITION p2 VALUES LESS THAN (200),
PARTITION p3 VALUES LESS THAN MAXVALUE);
INSERT INTO t1 SELECT 1, seq FROM seq_1_to_99;
INSERT INTO t1 SELECT 2, seq FROM seq_100_to_199;
INSERT INTO t1 SELECT 3, seq FROM seq_1_to_99;
ANALYZE TABLE t1 PERSISTENT FOR ALL;
Table Op Msg_type Msg_text
test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
EXPLAIN SELECT a, MIN(c) FROM t1 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range NULL a 10 NULL 4 Using index for group-by
SELECT a, MIN(c) FROM t1 GROUP BY a;
a MIN(c)
1 1
2 100
3 1
set @js='$out';
select json_extract(@js,'$**.partitions_index_scan_method');
json_extract(@js,'$**.partitions_index_scan_method')
["merge_ordered_scans"]
DROP TABLE t1;
# AFTER_KEY / BEFORE_KEY merged scan
CREATE TABLE t1 (a INT, b INT, c INT NOT NULL, PRIMARY KEY(a,c), KEY k(b,c))
ENGINE=InnoDB
PARTITION BY RANGE(c) (PARTITION p0 VALUES LESS THAN (10),
PARTITION p1 VALUES LESS THAN (20),
PARTITION p2 VALUES LESS THAN (30));
INSERT INTO t1 VALUES
(1,1,5),(2,2,7),(3,2,10),(4,1,15),(5,2,18),(6,0,22),(7,1,25);
EXPLAIN
SELECT MIN(c) FROM t1 WHERE b=1 AND c>5;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
FLUSH STATUS;
SELECT MIN(c) FROM t1 WHERE b=1 AND c>5;
MIN(c)
15
# 3 (merged: p0, p1, p2)
SHOW STATUS LIKE 'Handler_read_key';
Variable_name Value
Handler_read_key 3
EXPLAIN
SELECT MAX(c) FROM t1 WHERE b=1 AND c<25;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
FLUSH STATUS;
SELECT MAX(c) FROM t1 WHERE b=1 AND c<25;
MAX(c)
15
# 3 (merged: p0, p1, p2)
SHOW STATUS LIKE 'Handler_read_key';
Variable_name Value
Handler_read_key 3
DROP TABLE t1;
# KEY_OR_PREV needs a reverse partition scan.
# Ordered scan (HASH)
CREATE TABLE t1 (a INT, KEY k(a)) ENGINE=InnoDB
PARTITION BY HASH(a) PARTITIONS 3;
INSERT INTO t1 SELECT seq FROM seq_1_to_9;
HANDLER t1 OPEN;
HANDLER t1 READ k <= (5);
a
5
HANDLER t1 READ k PREV;
a
4
HANDLER t1 READ k PREV;
a
3
HANDLER t1 READ k <= (0);
a
HANDLER t1 CLOSE;
DROP TABLE t1;
# KEY_OR_PREV merged scan
CREATE TABLE t1 (a INT, b INT, c INT, PRIMARY KEY(a,c), KEY k(b,c))
ENGINE=InnoDB
PARTITION BY RANGE(c) (PARTITION p0 VALUES LESS THAN (10),
PARTITION p1 VALUES LESS THAN (20));
INSERT INTO t1 VALUES (1,1,5),(2,2,7),(3,1,15);
HANDLER t1 OPEN;
HANDLER t1 READ k <= (1,17);
a b c
3 1 15
HANDLER t1 READ k PREV;
a b c
1 1 5
HANDLER t1 CLOSE;
DROP TABLE t1;
# A range spanning several prefix values:
# QUICK_SELECT_DESC reads PREFIX_LAST_OR_PREV (2,15), keypart_map=b,c
CREATE TABLE t1 (a INT, b INT, c INT, PRIMARY KEY(a,c), KEY k(b,c)) ENGINE=InnoDB
PARTITION BY RANGE(c) (PARTITION p0 VALUES LESS THAN (10),
PARTITION p1 VALUES LESS THAN (20));
INSERT INTO t1 VALUES (1,1,7),(2,2,7),(3,1,12),(4,2,12);
EXPLAIN SELECT b, c FROM t1 FORCE INDEX(k)
WHERE b BETWEEN 1 AND 2 AND c BETWEEN 5 AND 15 ORDER BY b DESC, c DESC;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range k k 9 NULL 4 Using where; Using index
SELECT b, c FROM t1 FORCE INDEX(k)
WHERE b BETWEEN 1 AND 2 AND c BETWEEN 5 AND 15 ORDER BY b DESC, c DESC;
b c
2 12
2 7
1 12
1 7
set @js='$out';
select json_extract(@js,'$**.partitions_index_scan_method');
json_extract(@js,'$**.partitions_index_scan_method')
["merge_ordered_scans"]
DROP TABLE t1;
# reset m_unordered_prefix_len: single partition scan skips
# can_skip_merging_scans()
CREATE TABLE t1 (a INT, b INT, c INT, PRIMARY KEY(a,c),
KEY k(b,c), KEY kc(c,b)) ENGINE=InnoDB
PARTITION BY RANGE(c) (PARTITION p0 VALUES LESS THAN (10),
PARTITION p1 VALUES LESS THAN (20));
INSERT INTO t1 VALUES (1,1,5),(2,1,12),(3,2,13);
HANDLER t1 OPEN;
# 2 partitions, Case 2 on k(b,c): m_unordered_prefix_len = len(b)
HANDLER t1 READ k = (1);
a b c
1 1 5
# full key of kc binds c: single partition p1, reset
HANDLER t1 READ kc = (13,2);
a b c
3 2 13
# expect (2,1,12)
HANDLER t1 READ kc PREV;
a b c
2 1 12
HANDLER t1 CLOSE;
DROP TABLE t1;
Loading