Bug #52170 | innodb query optimizer fails (null possible_keys) with multicolumn key | ||
---|---|---|---|
Submitted: | 18 Mar 2010 9:57 | Modified: | 22 Mar 2010 10:43 |
Reporter: | Ethan Joffe | Email Updates: | |
Status: | Verified | Impact on me: | |
Category: | MySQL Server: Optimizer | Severity: | S5 (Performance) |
Version: | 5.1.44, mysql-next-mt | OS: | Linux (fc12) |
Assigned to: | CPU Architecture: | Any |
[18 Mar 2010 9:57]
Ethan Joffe
[18 Mar 2010 11:55]
Valeriy Kravchuk
Thank you for the problem report. Verified just as described: openxs@ubuntu:/home2/openxs/dbs/next-mr$ bin/mysql --no-defaults -uroot test Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 2 Server version: 5.6.99-m4-debug Source distribution Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> CREATE TABLE testdata ( -> ID int unsigned NOT NULL, -> ID2 int unsigned NOT NULL, -> val int unsigned NOT NULL, -> UNIQUE (ID, ID2) -> ) engine=InnoDB; Query OK, 0 rows affected (1.04 sec) mysql> insert into testdata (ID, ID2, val) values (1,1,1), (2,2,2), (3,3,3), (4,4,4); Query OK, 4 rows affected (0.06 sec) Records: 4 Duplicates: 0 Warnings: 0 mysql> explain select * from testdata where (ID, ID2) in ((1,1)); +----+-------------+----------+-------+---------------+------+---------+-------------+------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+----------+-------+---------------+------+---------+-------------+------+-------+ | 1 | SIMPLE | testdata | const | ID | ID | 8 | const,const | 1 | | +----+-------------+----------+-------+---------------+------+---------+-------------+------+-------+ 1 row in set (0.13 sec) mysql> explain select * from testdata where (ID, ID2)=(1,1) or (ID, ID2)=(3,3); +----+-------------+----------+-------+---------------+------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+----------+-------+---------------+------+---------+------+------+-------------+ | 1 | SIMPLE | testdata | range | ID | ID | 8 | NULL | 2 | Using where | +----+-------------+----------+-------+---------------+------+---------+------+------+-------------+ 1 row in set (0.18 sec) mysql> explain select * from testdata where (ID, ID2) in ((1,1), (3,3)); +----+-------------+----------+------+---------------+------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+----------+------+---------------+------+---------+------+------+-------------+ | 1 | SIMPLE | testdata | ALL | NULL | NULL | NULL | NULL | 4 | Using where | +----+-------------+----------+------+---------------+------+---------+------+------+-------------+ 1 row in set (0.03 sec)
[22 Mar 2010 10:43]
Ethan Joffe
I discovered the unfortunate additional fact that using the "OR" form of the query is not always a performance workaround for large datasets. Apparently the difference lies in type=range vs type=index. Sometimes, passing in the sets as a list using IN generates type=index, but as an OR'd list it shows up as type=range. Range takes orders of magnitudes longer when passing in a large list indexed against a table with a few million rows. Here is the output of the real world EXPLAIN, which I did not reduce to a simple example so I will leave the setup as an exercise for the reader... Here is using IN with the query running fast: id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE subidFeed range subidID subidID 8 NULL 102640 Using where; Using index Here is using OR with the query running slow: id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE subidFeed range subidID subidID 8 NULL 102640 Using where; Using index So apparently, sometimes the optimizer gets it right, although I find it annoying that in the first case it shows possible_keys as NULL even though it uses key subidID .