Bug #45969 | the query otimizer choose the wrong index | ||
---|---|---|---|
Submitted: | 6 Jul 2009 12:23 | Modified: | 8 Oct 2012 15:31 |
Reporter: | Manfred Wiedemeier | Email Updates: | |
Status: | Closed | Impact on me: | |
Category: | MySQL Server: Optimizer | Severity: | S3 (Non-critical) |
Version: | 5.1.35, 5.1.38-bzr | OS: | Windows (XP, Vista) |
Assigned to: | CPU Architecture: | Any | |
Tags: | regression |
[6 Jul 2009 12:23]
Manfred Wiedemeier
[6 Jul 2009 12:29]
Valeriy Kravchuk
OK, different index is used (this is related to partial fix for bug #28404 we have in 5.1.x). But why do you think this is a bug? Do you have seriously slower execution? Please, send also the results of: SELECT recid_r02, count(*) FROM r03 GROUP BY recid_r02 ORDER BY 2 DESC LIMIT 10; I want to know how many rows in the table may have particular recid_r02 value.
[20 Jul 2009 11:03]
Manfred Wiedemeier
I've got 85.000 records in R02 and 80.000 in R03. The execution time has changed from < 1 sec. to > 280 sec. SELECT recid_r02, count(*) FROM r03 GROUP BY recid_r02 ORDER BY 2 DESC LIMIT 10; recid_r02 count(*) 27256 3361 23569 3222 19452 3155 15370 3065 12801 2407 12796 1996 12793 1859 0 513 12802 301 29625 282
[22 Jul 2009 9:28]
Sveta Smirnova
Thank you for the feedback. I can not repeat described behavior: in case of MySQL-5.1 I get recid_r02 too. Please run OPTIMIZE TABLE on 5.1 server and inform us if it changed results.
[27 Jul 2009 8:36]
Manfred Wiedemeier
I optimize the tables, same result. The optimizer choose index `key6` and not `recid_r02`. If you like i can send you my database.
[27 Jul 2009 9:25]
Sveta Smirnova
Thank you for the feedback. > If you like i can send you my database. Yes, this would be good.
[27 Jul 2009 11:26]
Manfred Wiedemeier
I have uploaded "bug-data-45969.zip" to your ftp-server.
[30 Jul 2009 13:43]
Valeriy Kravchuk
Verified just as described using your tables uploaded with latest 5.1.38-bzr on Linux: openxs@suse:/home2/openxs/dbs/5.1> bin/mysql -uroot reg00003 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 1 Server version: 5.1.38-debug Source distribution Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> show tables; +--------------------+ | Tables_in_reg00003 | +--------------------+ | r02 | | r03 | +--------------------+ 2 rows in set (0.01 sec) mysql> explain SELECT r02.*, -> (SELECT r03.r_datum -> FROM r03 -> WHERE ((r03.recid_r02 = r02.recid) AND (r03.texttype IN (4,7,8,9))) -> ORDER BY r03.r_datum DESC -> LIMIT 1 -> ) AS last_order -> -> FROM r02 -> WHERE (r02.auftrag > 0) AND (r02.deleted = FALSE) -> ORDER BY r02.auftrag DESC -> LIMIT 50 -> -> ; +----+--------------------+-------+-------+---------------+------+---------+------+-------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+--------------------+-------+-------+---------------+------+---------+------+-------+-------------+ | 1 | PRIMARY | r02 | range | key | key | 4 | NULL | 27056 | Using where | | 2 | DEPENDENT SUBQUERY | r03 | index | recid_r02 | key6 | 3 | NULL | 1 | Using where | +----+--------------------+-------+-------+---------------+------+---------+------+-------+-------------+ 2 rows in set (0.02 sec) As you correctly noted index recid_r02 can be used: openxs@suse:/home2/openxs/dbs/5.1> bin/mysql -uroot reg00003 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 1 Server version: 5.1.38-debug Source distribution Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> show tables; +--------------------+ | Tables_in_reg00003 | +--------------------+ | r02 | | r03 | +--------------------+ 2 rows in set (0.01 sec) mysql> explain SELECT r02.*, -> (SELECT r03.r_datum -> FROM r03 -> WHERE ((r03.recid_r02 = r02.recid) AND (r03.texttype IN (4,7,8,9))) -> ORDER BY r03.r_datum DESC -> LIMIT 1 -> ) AS last_order -> -> FROM r02 -> WHERE (r02.auftrag > 0) AND (r02.deleted = FALSE) -> ORDER BY r02.auftrag DESC -> LIMIT 50 -> -> ; +----+--------------------+-------+-------+---------------+------+---------+------+-------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+--------------------+-------+-------+---------------+------+---------+------+-------+-------------+ | 1 | PRIMARY | r02 | range | key | key | 4 | NULL | 27056 | Using where | | 2 | DEPENDENT SUBQUERY | r03 | index | recid_r02 | key6 | 3 | NULL | 1 | Using where | +----+--------------------+-------+-------+---------------+------+---------+------+-------+-------------+ 2 rows in set (0.02 sec) mysql> explain SELECT r02.*, (SELECT r03.r_datum FROM r03 WHERE ((r03.recid_r02 = r02.recid) AND (r03.texttype IN (4,7,8,9))) ORDER BY r03.recid_r02, r03.r_datum DESC LIMIT 1 ) AS last_order FROM r02 WHERE (r02.auftrag > 0) AND (r02.deleted = FALSE) ORDER BY r02.auftrag DESC LIMIT 50; +----+--------------------+-------+-------+---------------+-----------+---------+--------------------+-------+-----------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+--------------------+-------+-------+---------------+-----------+---------+--------------------+-------+-----------------------------+ | 1 | PRIMARY | r02 | range | key | key | 4 | NULL | 27056 | Using where | | 2 | DEPENDENT SUBQUERY | r03 | ref | recid_r02 | recid_r02 | 4 | reg00003.r02.RECID | 3 | Using where; Using filesort | +----+--------------------+-------+-------+---------------+-----------+---------+--------------------+-------+-----------------------------+ 2 rows in set (0.00 sec) and, actually, query is much faster when it is used: mysql> SELECT r02.*, (SELECT r03.r_datum FROM r03 FORCE INDEX(recid_r02) WHERE ((r03.recid_r02 = r02.recid) AND (r03.texttype IN (4,7,8,9))) ORDER BY r03.r_datum DESC LIMIT 1 ) AS last_order FROM r02 WHERE (r02.auftrag > 0) AND (r02.deleted = FALSE) ORDER BY r02.auftrag DESC LIMIT 50; +-------+---------+---------+----------+--------------------------------------------------+----------+------------+ | RECID | DELETED | AUFTRAG | NACHTRAG | KURZBEZ | FLAGS | last_order | +-------+---------+---------+----------+--------------------------------------------------+----------+------------+ | 12803 | 0 | 50001 | 0 | Mustervorlage fr Dokumentation | 4096 | NULL | ... | 30399 | 0 | 42209 | 0 | Studentenversion | 768 | NULL | +-------+---------+---------+----------+--------------------------------------------------+----------+------------+ 50 rows in set (0.48 sec) mysql> SELECT r02.*, (SELECT r03.r_datum FROM r03 WHERE ((r03.recid_r02 = r02.recid) AND (r03.texttype IN (4,7,8,9))) ORDER BY r03.r_datum DESC LIMIT 1 ) AS last_order FROM r02 WHERE (r02.auftrag > 0) AND (r02.deleted = FALSE) ORDER BY r02.auftrag DESC LIMIT 50; +-------+---------+---------+----------+--------------------------------------------------+----------+------------+ | RECID | DELETED | AUFTRAG | NACHTRAG | KURZBEZ | FLAGS | last_order | +-------+---------+---------+----------+--------------------------------------------------+----------+------------+ | 12803 | 0 | 50001 | 0 | Mustervorlage fr Dokumentation | 4096 | NULL | ... | 30399 | 0 | 42209 | 0 | Studentenversion | 768 | NULL | +-------+---------+---------+----------+--------------------------------------------------+----------+------------+ 50 rows in set (1 min 5.75 sec) So, one minute instead of less than a second...
[21 Apr 2011 7:53]
Daniƫl van Eeden
As noted in support request 3-3357778341: - This also affects Linux x86-64, not only Microsoft Windows (XP,Vista) - This also affects version 5.5.8 (Enterprise), not only 5.1.35, 5.1.38-bzr Could this still be fixed in 5.5+ or should it target 5.6+?
[8 Oct 2012 15:31]
Paul DuBois
Noted in 5.6.8, 5.7.0 changelogs. For some queries involving ORDER BY, the optimizer chose the wrong index for accessing the table.