Bug #15907 Binary comparison ignores indexes
| Submitted: | 21 Dec 2005 15:23 | Modified: | 15 Dec 2009 17:37 |
|---|---|---|---|
| Reporter: | Jon Bright | Email Updates: | |
| Status: | Verified | Impact on me: | |
| Category: | MySQL Server: Optimizer | Severity: | S5 (Performance) |
| Version: | 5.0.19-BK, 5.0.13, 6.0.14-bzr | OS: | Linux (Linux) |
| Assigned to: | CPU Architecture: | Any |
[21 Dec 2005 15:23]
Jon Bright
[21 Dec 2005 16:05]
Jon Bright
I've just checked, this behaviour is the same on 5.0.16.
[21 Dec 2005 16:07]
Jon Bright
We originally experienced the behaviour on 4.1.12 - I've only done simple 2-row reproductions with 5.x. I've checked on 4.1.12, though, and the explain output isn't noticeably different.
[22 Dec 2005 17:51]
Valeriy Kravchuk
Thank you for a problem report. Verified just as described with 5.0.19-BK () build on Linux:
mysql> explain select a.somekey,a.foo from a right join b on a.somekey=b.somekey where
-> a.somekey is null;
+----+-------------+-------+-------+---------------+---------+---------+----------------+------+-------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+----------------+------+-------------------------+
| 1 | SIMPLE | b | index | NULL | PRIMARY | 12 | NULL | 2 | Using index |
x| 1 | SIMPLE | a | ref | PRIMARY | PRIMARY | 12 | test.b.somekey | 1 | Using where; Not exists |
+----+-------------+-------+-------+---------------+---------+---------+----------------+------+-------------------------+
2 rows in set (0.00 sec)
mysql> explain select a.somekey,a.foo from a right join b on binary a.somekey=binary
-> b.somekey where a.somekey is null;
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref |
rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------------------+
| 1 | SIMPLE | b | index | NULL | PRIMARY | 12 | NULL |
2 | Using index |
| 1 | SIMPLE | a | ALL | NULL | NULL | NULL | NULL |
1 | Using where; Not exists |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------------------+
2 rows in set (0.00 sec)
Your workaround from the older bug works (that bug is fixed in 5.0.19, I had checked):
mysql> explain select a.somekey,a.foo from a right join b on a.somekey=b.somekey and
-> binary a.somekey=binary b.somekey where a.somekey is null;
+----+-------------+-------+-------+---------------+---------+---------+----------------+------+-------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+----------------+------+-------------------------+
| 1 | SIMPLE | b | index | NULL | PRIMARY | 12 | NULL | 2 | Using index |
| 1 | SIMPLE | a | ref | PRIMARY | PRIMARY | 12 | test.b.somekey | 1 | Using where; Not exists |
+----+-------------+-------+-------+---------------+---------+---------+----------------+------+-------------------------+
2 rows in set (0.00 sec)
But I do not think it is a real problem. This query is slightly weird, I believe. For all other similar, but more reasonable queries there are no problems:
mysql> explain select a.somekey,a.foo from a right join b on a.somekey=b.somekey and
-> binary a.somekey=binary b.somekey where a.somekey is not null;
+----+-------------+-------+--------+---------------+---------+---------+-------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref| rows | Extra |
+----+-------------+-------+--------+---------------+---------+---------+-------+------+--------------------------+
| 1 | SIMPLE | a | system | PRIMARY | NULL | NULL | NULL| 1 | |
| 1 | SIMPLE | b | ref | PRIMARY | PRIMARY | 12 | const | 1 | Using where; Using index |
+----+-------------+-------+--------+---------------+---------+---------+-------+------+--------------------------+
2 rows in set (0.00 sec)
mysql> explain select a.somekey,a.foo from a right join b on a.somekey=b.somekey and binary a.somekey=binary b.somekey where a.somekey = 'ABCD';
+----+-------------+-------+--------+---------------+---------+---------+-------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+---------------+---------+---------+-------+------+--------------------------+
| 1 | SIMPLE | a | system | PRIMARY | NULL | NULL | NULL | 1 | |
| 1 | SIMPLE | b | ref | PRIMARY | PRIMARY | 12 | const | 1 | Using where; Using index |
+----+-------------+-------+--------+---------------+---------+---------+-------+------+--------------------------+
2 rows in set (0.01 sec)
[31 Aug 2006 16:22]
Igor Babaev
This performance problem can be also demonstrated with the following
simple example:
mysql> CREATE TABLE t1 (a char(10) PRIMARY KEY);
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO t1 VALUES ('aaaa'), ('bbbb'), ('dddd'), ('cccc');
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> CREATE TABLE t2 (a char(10) PRIMARY KEY);
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO t2 VALUES ('aaaa'), ('bbbb'), ('cccc'), ('eeee'), ('gggg'), ('hhhh');
Query OK, 6 rows affected (0.00 sec)
Records: 6 Duplicates: 0 Warnings: 0
mysql> EXPLAIN SELECT t1.a FROM t1,t2 WHERE t1.a=t2.a;
+----+-------------+-------+--------+---------------+---------+---------+-----------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+---------------+---------+---------+-----------+------+-------------+
| 1 | SIMPLE | t1 | index | PRIMARY | PRIMARY | 10 | NULL | 4 | Using index |
| 1 | SIMPLE | t2 | eq_ref | PRIMARY | PRIMARY | 10 | test.t1.a | 1 | Using index |
+----+-------------+-------+--------+---------------+---------+---------+-----------+------+-------------+
2 rows in set (0.00 sec)
mysql> EXPLAIN SELECT t1.a FROM t1,t2 WHERE binary t1.a = binary t2.a;
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
| 1 | SIMPLE | t1 | index | NULL | PRIMARY | 10 | NULL | 4 | Using index |
| 1 | SIMPLE | t2 | index | NULL | PRIMARY | 10 | NULL | 6 | Using where; Using index |
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
2 rows in set (0.01 sec)
mysql> EXPLAIN SELECT t1.a FROM t1,t2 WHERE t1.a=t2.a AND binary t1.a = binary t2.a;
+----+-------------+-------+--------+---------------+---------+---------+-----------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+---------------+---------+---------+-----------+------+--------------------------+
| 1 | SIMPLE | t1 | index | PRIMARY | PRIMARY | 10 | NULL | 4 | Using index |
| 1 | SIMPLE | t2 | eq_ref | PRIMARY | PRIMARY | 10 | test.t1.a | 1 | Using where; Using index |
+----+-------------+-------+--------+---------------+---------+---------+-----------+------+--------------------------+
2 rows in set (0.01 sec)
To fix this problem we have to be able to detect the cases
when we have in the WHERE condition a conjunctive predicate
of the form f1(t1.a)=f2(t2.a) such that
f1(t1.a)=f2(t2.a) => t1.a = t2.a and there is an
index that allow us to get the value t2.a from the value of
t1.a or vice versa.
In a general case this would require not a trivial check
procedure. That's why I mark this problem as 'To be fixed later'.
[28 Dec 2012 21:10]
Hartmut Holzgraefe
Just to show that this is not specific to the BINARY comparison operator: The same is happening with simple integer lookups in the form of indexed_column_value + 0 = some_constant mysql> create table t1(id int primary key, val int); Query OK, 0 rows affected (0.41 sec) mysql> insert into t1 values (1,1),(2,2),(23,42); Query OK, 3 rows affected (0.06 sec) Records: 3 Duplicates: 0 Warnings: 0 mysql> explain select * from t1 where id=23; +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+ | 1 | SIMPLE | t1 | const | PRIMARY | PRIMARY | 4 | const | 1 | | +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+ 1 row in set (0.01 sec) mysql> explain select * from t1 where id + 0 = 23; +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ | 1 | SIMPLE | t1 | ALL | NULL | NULL | NULL | NULL | 3 | Using where | +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ 1 row in set (0.00 sec)
Portions of this website are copyright © 2001, 2002 The PHP Group
Page generated in 0.044 sec. using MySQL 8.4.7-u6-cloud
Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the
respective copyright holders.
It is not reviewed in advance
by Oracle and does not necessarily represent the opinion of
Oracle or any other party.