Bug #51762 | Infinite loop when optimizing query | ||
---|---|---|---|
Submitted: | 5 Mar 2010 10:04 | Modified: | 6 Mar 2010 7:11 |
Reporter: | Ole John Aske | Email Updates: | |
Status: | Not a Bug | Impact on me: | |
Category: | MySQL Server: Optimizer | Severity: | S2 (Serious) |
Version: | 5.1.41,next-mr | OS: | Any |
Assigned to: | CPU Architecture: | Any |
[5 Mar 2010 10:04]
Ole John Aske
[5 Mar 2010 10:05]
Ole John Aske
mysqldump of test database
Attachment: dump.sql (text/x-sql), 139.14 KiB.
[5 Mar 2010 10:14]
Ole John Aske
This insanely large query was produced by RQG using the 'outer_join' grammar. Even though it might not be considered to be a relevant query, it seriously affects the testability of the server as it will cause RQG tests to stop after a few 1.000 queries.
[5 Mar 2010 13:48]
Valeriy Kravchuk
I was NOT able to repeat this hand with recent 5.1.45 from bzr and MyISAM engine instead of ndbcluster for the tables: openxs@suse:/home2/openxs/dbs/5.1> bin/mysql -uroot spj_ndb 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 5 Server version: 5.1.45-debug Source distribution Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> explain SELECT COUNT( table1 . `pk` ) AS field1 FROM CC AS table1 RIGHT JOIN C AS table2 ON table1 . `pk` = table2 . `int_key` RIGHT JOIN CC AS table3 ON table2 . `pk` = table3 . `int_key` LEFT OUTER JOIN C AS table4 RIGHT JOIN C AS table5 ON table4 . `int_key` = table5 . `pk` ON table2 . `int_key` = table4 . `int_key` LEFT JOIN CC AS table6 LEFT OUTER JOIN D AS table7 RIGHT JOIN C AS table8 ON table7 . `pk` = table8 . `pk` ON table6 . `pk` = table7 . `pk` ON table5 . `pk` = table8 . `int_key` LEFT JOIN CC AS table9 LEFT JOIN BB AS table10 ON table9 . `int_key` = table10 . `int_key` ON table3 . `pk` = table9 . `int_key` RIGHT JOIN CC AS table11 LEFT JOIN C AS table12 ON table11 . `pk` = table12 . `int_key` ON table5 . `int_key` = table12 . `int_key` LEFT JOIN C AS table13 ON table6 . `pk` = table13 . `int_key` LEFT JOIN C AS table14 RIGHT OUTER JOIN C AS table15 ON table14 . `int_key` = table15 . `int_key` LEFT JOIN CC AS table16 LEFT JOIN CC AS table17 ON table16 . `int_key` = table17 . `pk` LEFT JOIN C AS table18 ON table17 . `int_key` = table18 . `pk` ON table15 . `int_key` = table17 . `pk` ON table12 . `int_key` = table16 . `pk` WHERE table14 . `pk` >= table7 . `int_nokey` HAVING (field1 <= 9 OR field1 <> 1) ORDER BY field1 DESC; +----+-------------+---------+--------+-----------------+---------+---------+-------------------------+------+--------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+---------+--------+-----------------+---------+---------+-------------------------+------+--------------------------+ | 1 | SIMPLE | table2 | ALL | PRIMARY,int_key | NULL | NULL | NULL | 20 | Using temporary | | 1 | SIMPLE | table1 | eq_ref | PRIMARY | PRIMARY | 4 | spj_ndb.table2.int_key | 1 | Using index | | 1 | SIMPLE | table3 | ref | int_key | int_key | 5 | spj_ndb.table2.pk | 1 | Using where | | 1 | SIMPLE | table5 | eq_ref | PRIMARY,int_key | PRIMARY | 4 | spj_ndb.table2.int_key | 1 | Using where | | 1 | SIMPLE | table9 | ref | int_key | int_key | 5 | spj_ndb.table3.pk | 1 | Using index | | 1 | SIMPLE | table10 | ref | int_key | int_key | 5 | spj_ndb.table3.pk | 1 | Using index | | 1 | SIMPLE | table8 | ref | PRIMARY,int_key | int_key | 5 | spj_ndb.table2.int_key | 2 | Using where | | 1 | SIMPLE | table6 | eq_ref | PRIMARY | PRIMARY | 4 | spj_ndb.table8.pk | 1 | Using where; Using index | | 1 | SIMPLE | table11 | eq_ref | PRIMARY | PRIMARY | 4 | spj_ndb.table5.int_key | 1 | Using index | | 1 | SIMPLE | table16 | eq_ref | PRIMARY,int_key | PRIMARY | 4 | spj_ndb.table11.pk | 1 | Using where | | 1 | SIMPLE | table17 | eq_ref | PRIMARY | PRIMARY | 4 | spj_ndb.table16.int_key | 1 | Using where | | 1 | SIMPLE | table14 | ref | PRIMARY,int_key | int_key | 5 | spj_ndb.table16.int_key | 2 | Using where | | 1 | SIMPLE | table13 | ref | int_key | int_key | 5 | spj_ndb.table6.pk | 2 | Using index | | 1 | SIMPLE | table15 | ref | int_key | int_key | 5 | spj_ndb.table16.int_key | 2 | Using where; Using index | | 1 | SIMPLE | table4 | ref | int_key | int_key | 5 | spj_ndb.table5.pk | 2 | Using where; Using index | | 1 | SIMPLE | table12 | ref | int_key | int_key | 5 | spj_ndb.table16.pk | 2 | Using where; Using index | | 1 | SIMPLE | table18 | eq_ref | PRIMARY | PRIMARY | 4 | spj_ndb.table17.int_key | 1 | Using index | | 1 | SIMPLE | table7 | eq_ref | PRIMARY | PRIMARY | 4 | spj_ndb.table8.pk | 1 | Using where | +----+-------------+---------+--------+-----------------+---------+---------+-------------------------+------+--------------------------+ 18 rows in set (29.13 sec) mysql> show create table C\G *************************** 1. row *************************** Table: C Create Table: CREATE TABLE `C` ( `pk` int(11) NOT NULL AUTO_INCREMENT, `int_nokey` int(11) DEFAULT NULL, `int_key` int(11) DEFAULT NULL, `date_key` date DEFAULT NULL, `date_nokey` date DEFAULT NULL, `time_key` time DEFAULT NULL, `time_nokey` time DEFAULT NULL, `datetime_key` datetime DEFAULT NULL, `datetime_nokey` datetime DEFAULT NULL, `varchar_key` varchar(1) DEFAULT NULL, `varchar_nokey` varchar(1) DEFAULT NULL, PRIMARY KEY (`pk`), KEY `int_key` (`int_key`), KEY `date_key` (`date_key`), KEY `time_key` (`time_key`), KEY `datetime_key` (`datetime_key`), KEY `varchar_key` (`varchar_key`,`int_key`) ) ENGINE=MyISAM AUTO_INCREMENT=21 DEFAULT CHARSET=latin1 1 row in set (0.01 sec) EXPLAIN is slow, but it works. So, please, check with a newer version, 5.1.44. Also if the bug is repeatable with ndbcluster tables only, then Optimizer category is wrong here.
[5 Mar 2010 14:15]
Ole John Aske
I assume you created the database using RQGs gendata-old? I have a minor modification in my local GendataSimple.pm which I assumed didn't matter: It defines the column int_key as 'UNIQUE KEY': CREATE TABLE `C` ( `pk` int(11) NOT NULL AUTO_INCREMENT, `int_nokey` int(11) DEFAULT NULL, `int_key` int(11) DEFAULT NULL, `date_key` date DEFAULT NULL, `date_nokey` date DEFAULT NULL, `time_key` time DEFAULT NULL, `time_nokey` time DEFAULT NULL, `datetime_key` datetime DEFAULT NULL, `datetime_nokey` datetime DEFAULT NULL, `varchar_key` varchar(1) DEFAULT NULL, `varchar_nokey` varchar(1) DEFAULT NULL, PRIMARY KEY (`pk`), UNIQUE KEY `int_key` (`int_key`), KEY `date_key` (`date_key`), KEY `time_key` (`time_key`), KEY `datetime_key` (`datetime_key`), KEY `varchar_key` (`varchar_key`,`int_key`) ) ENGINE=MyISAM AUTO_INCREMENT=12 DEFAULT CHARSET=latin1 | I don't know if this makes any difference.... Re. MyISAM vs Cluster - This is actually a MyIsam problem only. On Cluster the explain - and execution - is almost instant. Probably due to different access plan generated as the calculated 'costs' may be different for the SEs.
[5 Mar 2010 14:31]
Ole John Aske
Tested UNIQUE KEY vs non-UNIQUE myself: explain, non-UNIQUE: 1 min 29 sec explain UNIQUE:
[5 Mar 2010 14:35]
Ole John Aske
Tested UNIQUE KEY vs non-UNIQUE myself: explain, non-UNIQUE: 1 min, 29 sec explain UNIQUE: 12 min, 15 sec Not entirely an infinite loop, but obviously some bad optimizer decissions are made as ndbcluster explains the same query in virtually no time.
[6 Mar 2010 7:11]
Philip Stoev
Hello. I am afraid that this is not a genuine bug. The reason for the slow EXPLAIN is that the optimizer does an exhaustive search of all possibilities, which takes time, especially if there are numerous tables that are not differentiated, that is, no join order is better than any other, since all tables contain random data with a flat distribution. To fix this, use optimizer_search_depth=10 and the EXPLAIN will complete within 0.1 seconds. Thank you.