Bug #77340 | Optimizer chooses wrong index for LEFT JOIN query | ||
---|---|---|---|
Submitted: | 12 Jun 2015 22:34 | Modified: | 18 Dec 2015 10:58 |
Reporter: | Sveta Smirnova (OCA) | Email Updates: | |
Status: | Verified | Impact on me: | |
Category: | MySQL Server: Optimizer | Severity: | S3 (Non-critical) |
Version: | 5.6.25, 5.7.7 | OS: | Any |
Assigned to: | CPU Architecture: | Any |
[12 Jun 2015 22:34]
Sveta Smirnova
[12 Jun 2015 22:38]
Sveta Smirnova
First two tables, necessary to repeat the bug
Attachment: issue53536_renamed.sql.1.gz (application/gzip, text), 2.64 MiB.
[12 Jun 2015 22:39]
Sveta Smirnova
Third table, necessary to repeat this bug
Attachment: issue53536_renamed.sql.2.gz (application/gzip, text), 670.81 KiB.
[12 Jun 2015 22:42]
Sveta Smirnova
Originally reported at https://bugs.launchpad.net/percona-server/+bug/1464789
[13 Jun 2015 23:36]
MySQL Verification Team
Thank you for the bug version. Version 5.5 not affected. C:\dbs>c:\dbs\5.5\bin\mysql -uroot --port=3550 --prompt="mysql 5.5 > " Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 3 Server version: 5.5.45-log Source distribution PULL: 2015/06/05 mysql 5.5 > use test Database changed mysql 5.5 > SHOW VARIABLES LIKE "innodb_file_format"; +--------------------+-----------+ | Variable_name | Value | +--------------------+-----------+ | innodb_file_format | Barracuda | +--------------------+-----------+ 1 row in set (0.00 sec) mysql 5.5 > flush tables; flush status; Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected (0.00 sec) mysql 5.5 > SELECT COUNT(DISTINCT `t1`.`id`) FROM `t1` INNER JOIN `t2` ON `t2`.`id` = `t1`.`f1` LEFT OUTER JOIN `t3` ON `t3`.`f1` = `t1`.`id` AND t3.f3 IS NULL AND `t3`.`f4` = 'Entry' LEFT OUTER JOIN `t3` `thumbnails_t3` ON `thumbnails_t3`.`f3` = `t3`.`id` WHE RE `t1`.`f2` IS NULL AND `t1`.`f3` = 85260 AND (t1.f3 = 85260 AND t2.f2 IS NULL); +---------------------------+ | COUNT(DISTINCT `t1`.`id`) | +---------------------------+ | 512 | +---------------------------+ 1 row in set (0.00 sec) mysql 5.5 > show status like 'Handler_%'; +----------------------------+-------+ | Variable_name | Value | +----------------------------+-------+ | Handler_commit | 1 | | Handler_delete | 0 | | Handler_discover | 0 | | Handler_prepare | 0 | | Handler_read_first | 0 | | Handler_read_key | 514 | | Handler_read_last | 0 | | Handler_read_next | 512 | | Handler_read_prev | 0 | C:\dbs>c:\dbs\5.6\bin\mysql -uroot --port=3560 -p --prompt="mysql 5.6 > " Enter password: ****** Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 2 Server version: 5.6.26 Source distribution PULL 2015/06/05 mysql 5.6 > use test Database changed mysql 5.6 > SHOW VARIABLES LIKE "innodb_file_format"; +--------------------+-----------+ | Variable_name | Value | +--------------------+-----------+ | innodb_file_format | Barracuda | +--------------------+-----------+ 1 row in set (0.00 sec) mysql 5.6 > flush tables; flush status; Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected (0.00 sec) mysql 5.6 > SELECT COUNT(DISTINCT `t1`.`id`) FROM `t1` INNER JOIN `t2` ON `t2`.`id` = `t1`.`f1` LEFT OUTER JOIN `t3` ON `t3`.`f1` = `t1`.`id` AND t3.f3 IS NULL AND `t3`.`f4` = 'Entry' LEFT OUTER JOIN `t3` `thumbnails_t3` ON `thumbnails_t3`.`f3` = `t3`.`id` WHE RE `t1`.`f2` IS NULL AND `t1`.`f3` = 85260 AND (t1.f3 = 85260 AND t2.f2 IS NULL); +---------------------------+ | COUNT(DISTINCT `t1`.`id`) | +---------------------------+ | 512 | +---------------------------+ 1 row in set (0.30 sec) mysql 5.6 > show status like 'Handler_%'; +----------------------------+--------+ | Variable_name | Value | +----------------------------+--------+ | Handler_commit | 1 | | Handler_delete | 0 | | Handler_discover | 0 | | Handler_external_lock | 8 | | Handler_mrr_init | 0 | | Handler_prepare | 0 | | Handler_read_first | 0 | | Handler_read_key | 514 | | Handler_read_last | 0 | | Handler_read_next | 512512 | | Handler_read_prev | 0 | mysql 5.6 > flush tables; flush status; Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected (0.00 sec) mysql 5.6 > SELECT COUNT(DISTINCT `t1`.`id`) FROM `t1` INNER JOIN `t2` ON `t2`.`id` = `t1`.`f1` LEFT OUTER JOIN `t3` force index(f1) ON `t3`.`f1` = `t1`.`id` AND t3.f3 IS NULL AND `t3`.`f4` = 'Entry' LEFT OUTER JOIN `t3` `thumbnails_t3` ON `thumbnails_t3`.`f3` = `t3`.`id` WHERE `t1`.`f2` IS NULL AND `t1`.`f3` = 85260 AND (t1.f3 = 85260 AND t2.f2 IS NULL); +---------------------------+ | COUNT(DISTINCT `t1`.`id`) | +---------------------------+ | 512 | +---------------------------+ 1 row in set (0.00 sec) mysql 5.6 > show status like 'Handler_%'; +----------------------------+-------+ | Variable_name | Value | +----------------------------+-------+ | Handler_commit | 1 | | Handler_delete | 0 | | Handler_discover | 0 | | Handler_external_lock | 8 | | Handler_mrr_init | 0 | | Handler_prepare | 0 | | Handler_read_first | 0 | | Handler_read_key | 514 | | Handler_read_last | 0 | | Handler_read_next | 512 | | Handler_read_prev | 0 | C:\dbs>c:\dbs\5.7\bin\mysql -uroot -p --port=3570 --prompt="mysql 5.7 > " Enter password: ****** Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 3 Server version: 5.7.8-rc Source distribution PULL 2015/06/05 mysql 5.7 > use test Database changed mysql 5.7 > SHOW VARIABLES LIKE "innodb_file_format"; +--------------------+-----------+ | Variable_name | Value | +--------------------+-----------+ | innodb_file_format | Barracuda | +--------------------+-----------+ 1 row in set, 1 warning (0.00 sec) mysql 5.7 > flush tables; flush status; Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected (0.00 sec) mysql 5.7 > SELECT COUNT(DISTINCT `t1`.`id`) FROM `t1` INNER JOIN `t2` ON `t2`.`id` = `t1`.`f1` LEFT OUTER JOIN `t3` ON `t3`.`f1` = `t1`.`id` AND t3.f3 IS NULL AND `t3`.`f4` = 'Entry' LEFT OUTER JOIN `t3` `thumbnails_t3` ON `thumbnails_t3`.`f3` = `t3`.`id` WHE RE `t1`.`f2` IS NULL AND `t1`.`f3` = 85260 AND (t1.f3 = 85260 AND t2.f2 IS NULL); +---------------------------+ | COUNT(DISTINCT `t1`.`id`) | +---------------------------+ | 512 | +---------------------------+ 1 row in set (0.38 sec) mysql 5.7 > show status like 'Handler_%'; +----------------------------+--------+ | Variable_name | Value | +----------------------------+--------+ | Handler_commit | 1 | | Handler_delete | 0 | | Handler_discover | 0 | | Handler_external_lock | 9 | | Handler_mrr_init | 0 | | Handler_prepare | 0 | | Handler_read_first | 1 | | Handler_read_key | 514 | | Handler_read_last | 0 | | Handler_read_next | 512512 | | Handler_read_prev | 0 | | Handler_read_rnd | 0 | | Handler_read_rnd_next | 26 | | Handler_rollback | 0 | | Handler_savepoint | 0 | | Handler_savepoint_rollback | 0 | | Handler_update | 0 | | Handler_write | 0 | +----------------------------+--------+ 18 rows in set (0.00 sec)
[18 Dec 2015 10:58]
Sveta Smirnova
EXPLAIN FORMAT=JSON cost_info for the slow query: "cost_info": { "query_cost": "1212.09" }, For the fast query: "cost_info": { "query_cost": "2349.71" }, For t3 in the slow query: "cost_info": { "read_cost": "191.75", "eval_cost": "38.35", "prefix_cost": "875.62", "data_read_per_join": "196K" }, For t3 in the fast query: "cost_info": { "read_cost": "273.36", "eval_cost": "54.67", "prefix_cost": "1870.04", "data_read_per_join": "279K" }, Looks like these calculations wrong, at least overall query cost.