Bug #34364 | LEFT JOIN with subquery takes very long time | ||
---|---|---|---|
Submitted: | 6 Feb 2008 21:17 | Modified: | 30 Jul 2012 17:14 |
Reporter: | Ratan Mohla | Email Updates: | |
Status: | Closed | Impact on me: | |
Category: | MySQL Server: Optimizer | Severity: | S1 (Critical) |
Version: | 5.1.22 | OS: | Solaris (SunOS clapton.nms.fnc.fujitsu.com 5.10 Generic_118833-36 sun4u sparc SUNW,Ultra-4) |
Assigned to: | CPU Architecture: | Any |
[6 Feb 2008 21:17]
Ratan Mohla
[7 Feb 2008 4:35]
Valeriy Kravchuk
Thank you for a problem report. Please, send a complete test case (with some data for tables involved to demostrate the problem) or at least SHOW CREATE TABLE and SHOW TABLE STATUS results for the tables involved.
[7 Feb 2008 19:47]
Ratan Mohla
test schema and some data populated
Attachment: omvmomua_small.dmp.gz (application/gzip, text), 398.09 KiB.
[7 Feb 2008 19:47]
Ratan Mohla
perl script to generate large data
Attachment: db_mysql_griphon_10wayjoin.pl (application/octet-stream, text), 9.60 KiB.
[24 Feb 2008 13:45]
Valeriy Kravchuk
I see 5.0.18-debug-log as a server version in the dump you uploaded. So, what version do you have this bug in? Have you tried to check with 5.1.23-rc or 5.0.54?
[25 Feb 2008 11:56]
Valeriy Kravchuk
I had loaded your test case. Actually, this is a know limitation of MySQL's optimizer: mysql> explain SELECT objectmeta.name AS objname -> , IFNULL(NV1.value,'NULL') AS "projectName" -> , objectmeta.objId , IFNULL(NV2.value,'NULL') AS "NEType" -> , objectmeta.objectState -> , objectmeta.lastModifiedBy -> , objectmeta.lastModificationTime , objectmeta.description -> , objectmeta.creationTime , objectmeta.objectType -> , objectmeta.createdBy -> FROM objectmeta -> LEFT JOIN -> (select oid,name,value from objectmeta_userattributes where name = 'pro jectName') NV1 -> ON objectmeta.oid=NV1.oid -> LEFT JOIN (select oid,name,value from objectmeta_userattributes where n ame = 'NEType') -> NV2 -> ON objectmeta.oid=NV2.oid -> WHERE objectmeta.oid IN (select versionmeta_objectmeta from versionmeta -> where versionmeta.createdby = 'netsmart' and ve rsionState = '1') -> ORDER by 7 desc; +----+--------------------+---------------------------+----------------+-------- ---------------------------+------------------+---------+------+--------+------- ---------------------------------------+ | id | select_type | table | type | possibl e_keys | key | key_len | ref | rows | Extra | +----+--------------------+---------------------------+----------------+-------- ---------------------------+------------------+---------+------+--------+------- ---------------------------------------+ | 1 | PRIMARY | <derived3> | system | NULL | NULL | NULL | NULL | 0 | const row not found | | 1 | PRIMARY | objectmeta | ALL | NULL | NULL | NULL | NULL | 759423 | Using where; Using temporary; Using filesort | | 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 61360 | | | 4 | DEPENDENT SUBQUERY | versionmeta | index_subquery | sk_vers ionmeta_1,sk_versionmeta_2 | sk_versionmeta_2 | 19 | func | 1 | Using where | | 3 | DERIVED | objectmeta_userattributes | ALL | NULL | NULL | NULL | NULL | 317131 | Using where | | 2 | DERIVED | objectmeta_userattributes | ALL | NULL | NULL | NULL | NULL | 317131 | Using where | +----+--------------------+---------------------------+----------------+-------- ---------------------------+------------------+---------+------+--------+------- ---------------------------------------+ 6 rows in set (3.07 sec) Subquery to versionmeta table is considered DEPENDENT, while it is NOT. And using JOIN instead of such a subquery is a known good workaround. This problem should be fixed in 6.0.x. I'll prove it in my next comment.
[25 Feb 2008 12:57]
Valeriy Kravchuk
Now, let's check the plan in 6.0.x: openxs@linux:~/dbs/6.0> bin/mysql -uroot Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 4 Server version: 6.0.5-alpha Source distribution Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> use test Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> explain SELECT objectmeta.name AS objname -> , IFNULL(NV1.value,'NULL') AS "projectName" -> , objectmeta.objId , IFNULL(NV2.value,'NULL') AS "NEType" -> , objectmeta.objectState -> , objectmeta.lastModifiedBy -> , objectmeta.lastModificationTime , objectmeta.description -> , objectmeta.creationTime , objectmeta.objectType -> , objectmeta.createdBy -> FROM objectmeta -> LEFT JOIN -> (select oid,name,value from objectmeta_userattributes where name = 'pro jectName') NV1 -> ON objectmeta.oid=NV1.oid -> LEFT JOIN (select oid,name,value from objectmeta_userattributes where n ame = 'NEType') -> NV2 O -> ON objectmeta.oid=NV2.oid -> WHERE objectmeta.oid IN (select versionmeta_objectmeta from versionmeta -> where versionmeta.createdby = 'netsmart' and ve rsionState = '1') -> ORDER by 7 desc; +----+-------------+---------------------------+--------+----------------------- ------------+------------------+---------+-------------------------------------- ---+--------+---------------------------------------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+---------------------------+--------+----------------------- ------------+------------------+---------+-------------------------------------- ---+--------+---------------------------------------------------------------+ | 1 | PRIMARY | <derived3> | system | NULL | NULL | NULL | NULL | 0 | const row not found | | 1 | PRIMARY | versionmeta | ref | sk_versionmeta_1,sk_ve rsionmeta_2 | sk_versionmeta_1 | 3 | const | 10 | Using where; Using temporary; Using filesort; Start temporary | | 1 | PRIMARY | objectmeta | eq_ref | PRIMARY | PRIMARY | 18 | test.versionmeta.VersionMeta_ObjectMe ta | 1 | End temporary | | 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 61360 | | | 3 | DERIVED | objectmeta_userattributes | ALL | NULL | NULL | NULL | NULL | 336170 | Using where | | 2 | DERIVED | objectmeta_userattributes | ALL | NULL | NULL | NULL | NULL | 336170 | Using where | +----+-------------+---------------------------+--------+----------------------- ------------+------------------+---------+-------------------------------------- ---+--------+---------------------------------------------------------------+ 6 rows in set (5.38 sec) So, as you can see, no DEPENDENT rows in the plan. This problem should be already fixed in 6.0.3-alpha, but it is unlikely for this fix to appear in 5.0 or 5.1 any time soon (as too many changes in code will be introduced). Please, check if execution time for this query in 6.0.3 is acceptable in your environment.
[25 Feb 2008 19:01]
Ratan Mohla
Thank you very much for the analysis and investigation on the query optimization issue. To answer your question, we did test this query in 5.1.22 version earlier and the performance is same as that in 5.0.54 or 5.0.18. and the explain output is the same also. So, the problem still exists in 5.1.22. From our perspective, since 6.0.3 is in alpha stage, and we cannot use 6.0 in our product until it is GA release, and since it is still very long I guess it is possible that the GA will be as much as a year and a half which will be a very long time to wait. Since we are migrating from oracle to mysql, this is a very big issue for us, and since we know that this bug will be fixed in 6.0, it does not make sense for us to do the code changes as the code changes are not minor, it is going to take huge amount of code changes at may places since we are using this query pattern very extensively (from 2 way joins upto 10 way joins) and will require us to change a lot of XML and JAVA files along with unit, system and performance testing which will be too much time and effort. It is good to know that this issue is addressed in 6.0 and as I understand it solves a lot of other subquery optimization issues and not just the bug reported by me. But it is going to be a lot of help to us if we can at least somehow just translate the subquery reported in this bug to the join (since we use only this subquery pattern) and let join be optimized since we know that join performance is very good in 5.1. We do not need all the subquery cases where the subquery optimization can be done and we will be ok if they are addressed in 6.0.
[26 Feb 2008 18:26]
Timothy Smith
Hi. I am sorry to bring bad news, but the extensive changes needed to improve the subquery optimization are not likely to be backported to MySQL 5.1. With apologies, Timothy
[30 Jul 2012 17:14]
Paul DuBois
Noted in 5.6.6 changelog. LEFT JOIN on derived tables was very slow. This is now addressed through the use of subquery materialization.