diff options
author | Sergey Petrunya <psergey@askmonty.org> | 2011-08-05 22:01:49 +0400 |
---|---|---|
committer | Sergey Petrunya <psergey@askmonty.org> | 2011-08-05 22:01:49 +0400 |
commit | 0e19f3e36f7842583feb6bead2c2600cd620bced (patch) | |
tree | 3b0bcc798ddfd4b469f39f285daa697f8c1ef614 /mysql-test/r/range_mrr_icp.result | |
parent | 332b47d718e1f25d553021819ded06961ddd4e56 (diff) | |
download | mariadb-git-0e19f3e36f7842583feb6bead2c2600cd620bced.tar.gz |
Backport of:
revno: 2876.47.174
revision-id: jorgen.loland@oracle.com-20110519120355-qn7eprkad9jqwu5j
parent: mayank.prasad@oracle.com-20110518143645-bdxv4udzrmqsjmhq
committer: Jorgen Loland <jorgen.loland@oracle.com>
branch nick: mysql-trunk-11765831
timestamp: Thu 2011-05-19 14:03:55 +0200
message:
BUG#11765831: 'RANGE ACCESS' MAY INCORRECTLY FILTER
AWAY QUALIFYING ROWS
The problem was that the ranges created when OR'ing two
conditions could be incorrect. Without the bugfix,
"I <> 6 OR (I <> 8 AND J = 5)" would create these ranges:
"NULL < I < 6",
"6 <= I <= 6 AND 5 <= J <= 5",
"6 < I < 8",
"8 <= I <= 8 AND 5 <= J <= 5",
"8 < I"
While the correct ranges is
"NULL < I < 6",
"6 <= I <= 6 AND 5 <= J <= 5",
"6 < I"
The problem occurs when key_or() ORs
(1) "NULL < I < 6, 6 <= I <= 6 AND 5 <= J <= 5, 6 < I" with
(2) "8 < I AND 5 <= J <= 5"
The reason for the bug is that in key_or(), SEL_ARG *tmp is
used to point to the range in (1) above that is merged with
(2) while key1 points to the root of the red-black tree of
(1). When merging (1) and (2), tmp refers to the "6 < I"
part whereas the root is the "6 <= ... AND 5 <= J <= 5" part.
key_or() decides that the tmp range needs to be split into
"6 < I < 8, 8 <= I <= 8, 8 < I", in which next_key_part of the
second range should be that of tmp. However, next_key_part is
set to key1->next_key_part ("5 <= J <= 5") instead of
tmp->next_key_part (empty). Fixing this gives the correct but
not optimal ranges:
"NULL < I < 6",
"6 <= I <= 6 AND 5 <= J <= 5",
"6 < I < 8",
"8 <= I <= 8",
"8 < I"
A second problem can be seen above: key_or() may create
adjacent ranges that could be replaced with a single range.
Fixes for this is also included in the patch so that the range
above becomes correct AND optimal:
"NULL < I < 6",
"6 <= I <= 6 AND 5 <= J <= 5",
"6 < I"
Merging adjacent ranges like this gives a slightly lower cost
estimate for the range access.
Diffstat (limited to 'mysql-test/r/range_mrr_icp.result')
-rw-r--r-- | mysql-test/r/range_mrr_icp.result | 48 |
1 files changed, 47 insertions, 1 deletions
diff --git a/mysql-test/r/range_mrr_icp.result b/mysql-test/r/range_mrr_icp.result index f98b91027c9..fdd8c6ca7ba 100644 --- a/mysql-test/r/range_mrr_icp.result +++ b/mysql-test/r/range_mrr_icp.result @@ -1,6 +1,6 @@ set @mrr_icp_extra_tmp=@@optimizer_switch; set optimizer_switch='mrr=on,mrr_sort_keys=on,index_condition_pushdown=on'; -drop table if exists t1, t2, t3; +drop table if exists t1, t2, t3, t10, t100; CREATE TABLE t1 ( event_date date DEFAULT '0000-00-00' NOT NULL, type int(11) DEFAULT '0' NOT NULL, @@ -1765,4 +1765,50 @@ select min(f1) from t1 where f1 >= '2006-05-25 07:00:20' and f1 between '2003- min(f1) NULL drop table t1; +# +# BUG#11765831: 'RANGE ACCESS' MAY INCORRECTLY FILTER +# AWAY QUALIFYING ROWS +# +CREATE TABLE t10( +K INT NOT NULL AUTO_INCREMENT, +I INT, J INT, +PRIMARY KEY(K), +KEY(I,J) +); +INSERT INTO t10(I,J) VALUES (6,1),(6,2),(6,3),(6,4),(6,5), +(6,6),(6,7),(6,8),(6,9),(6,0); +CREATE TABLE t100 LIKE t10; +INSERT INTO t100(I,J) SELECT X.I, X.K+(10*Y.K) FROM t10 AS X,t10 AS Y; +INSERT INTO t100(I,J) VALUES(8,26); + +EXPLAIN SELECT * FROM t100 WHERE I <> 6 OR (I <> 8 AND J = 5); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t100 range I I 10 NULL 4 Using index condition; Rowid-ordered scan + +SELECT * FROM t100 WHERE I <> 6 OR (I <> 8 AND J = 5); +K I J +101 8 26 +DROP TABLE t10,t100; +# +# lp:817363: Wrong result with sort_union and multipart key in maria-5.3 +# +CREATE TABLE t1 (a int NOT NULL , b int, c int, d varchar(32), KEY (d,b), PRIMARY KEY (a)) ; +INSERT INTO t1 VALUES (7,7,NULL,'e'),(8,1,0,'p'),(9,7,1,'s'),(10,1,1,'j'),(12,2,0,'c'),(13,0,0,'a'),(14,1,1,'q'); +SELECT c FROM t1 WHERE d='q' OR d>='q' OR a > 97 OR (d IN ('j','s','i') AND b = 102); +c +1 +1 +SELECT c FROM t1 ignore index (d) WHERE d='q' OR d>='q' OR a > 97 OR (d IN ('j','s','i') AND b = 102); +c +1 +1 +SELECT * FROM t1 ignore index(d) WHERE d = 'q' OR d >= 'q' OR (d IN ( 'j' , 's' , 'i' ) AND ( b = 102 )); +a b c d +9 7 1 s +14 1 1 q +SELECT * FROM t1 force index(d) WHERE d = 'q' OR d >= 'q' OR (d IN ( 'j' , 's' , 'i' ) AND ( b = 102 )); +a b c d +9 7 1 s +14 1 1 q +DROP TABLE t1; set optimizer_switch=@mrr_icp_extra_tmp; |