| Bug #37902 | Bug (2) in the query optimizer (explain) | ||
|---|---|---|---|
| Submitted: | 6 Jul 2008 15:14 | Modified: | 27 Jul 2008 18:42 |
| Reporter: | Alejandro Cusumano | Email Updates: | |
| Status: | Verified | Impact on me: | |
| Category: | MySQL Server: Optimizer | Severity: | S3 (Non-critical) |
| Version: | 5.0.45, 5.0.68 | OS: | MacOS |
| Assigned to: | CPU Architecture: | Any | |
[6 Jul 2008 17:49]
Valeriy Kravchuk
Thank you for a problem report. What exact version of MySQL server you had used? What is the the file name of a test case data for this bug on FTP server?
[6 Jul 2008 18:07]
Alejandro Cusumano
The filename is in the format suggested by the instructions - 'bug-data-37902.zip' Version updated in report metadata.
[27 Jul 2008 18:42]
Valeriy Kravchuk
EXPLAIN is slow because MySQL has to "materialize" derived tables while executing EXPLAIN. This is a known problem. This also explain while subsequent execution is much faster - data are mostly still in the buffer(s).
I'd consider a (new) bug here the fact that after this SELECT (left derived table in LEFT JOIN):
mysql> explain select o.dbx_tx, count(*) AS null_cnt from pizza_orders o join pizza_line_items li on o.id = li.order_id where li.type = 'ProductLineItem' and li.product_id is null and o.id >= 700000 group by o.dbx_tx
-> ;
+----+-------------+-------+-------+---------------------+----------+---------+-----------+--------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------------+----------+---------+-----------+--------+----------------------------------------------+
| 1 | SIMPLE | o | range | PRIMARY | PRIMARY | 4 | NULL | 201413 | Using where; Using temporary; Using filesort |
| 1 | SIMPLE | li | ref | order_id,product_id | order_id | 5 | test.o.id | 1 | Using where |
+----+-------------+-------+-------+---------------------+----------+---------+-----------+--------+----------------------------------------------+
2 rows in set (0.04 sec)
mysql> select o.dbx_tx, count(*) AS null_cnt from pizza_orders o join pizza_line_items li on o.id = li.order_id where li.type = 'ProductLineItem' and li.product_id is null and o.id >= 700000 group by o.dbx_tx
-> ;
Empty set (1 min 27.82 sec)
server does NOT stop executing right part of LEFT JOIN immediately. As as result, it executes a pointless SELECT with dependent subquery, where the overall query spends most of the time.

Description: A query in mysql takes a very long time to explain (~25/40 seconds), and less time to run (variable between 1 < t < 25 secs), while in PostgreSQL it takes less than a second for both operations. Details follow. Note: the data has been transferred to PostgreSQL with a commercial converter. There is no 100% guarantee that the data is exactly the same, but it's very unlikely that a difference in the data can cause such a difference in the query timings. --------------------------------------------- The query is: explain select * from ( select o.dbx_tx, count(*) AS null_cnt from pizza_orders o join pizza_line_items li on o.id = li.order_id where li.type = 'ProductLineItem' and li.product_id is null and o.id >= 700000 group by o.dbx_tx ) sn left join ( select o.dbx_tx, count(*) AS no_null_cnt from pizza_orders o join pizza_line_items li on o.id = li.order_id where li.type = 'TicketLineItem' and exists (select * from pizza_line_items li2 where li2.order_id = li.order_id and type = 'ProductLineItem' and product_id is null) and o.id >= 700000 group by o.dbx_tx ) snn on sn.dbx_tx = snn.dbx_tx order by sn.dbx_tx; --------------------------------------------- The tables are: CREATE TABLE `pizza_orders` ( `id` int(11) NOT NULL, `dbx_tx` varchar(10) default NULL, PRIMARY KEY (`id`), KEY `dbx_tx` (`dbx_tx`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; CREATE TABLE `pizza_line_items` ( `id` int(11) NOT NULL, `order_id` int(11) default NULL, `type` varchar(255) default NULL, `product_id` int(11) default NULL, PRIMARY KEY (`id`), KEY `order_id` (`order_id`), KEY `product_id` (`product_id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; --------------------------------------------- The dataset has been sent via FTP. --------------------------------------------- How to repeat: Details given in the description. Suggested fix: Too unpolite to write in a public forum.