Bug #41740 | MySQL 5.1 optimizer produces inefficient plan for complex queries | ||
---|---|---|---|
Submitted: | 25 Dec 2008 8:51 | Modified: | 16 Aug 2011 1:21 |
Reporter: | Valeriy Kravchuk | Email Updates: | |
Status: | Closed | Impact on me: | |
Category: | MySQL Server: Optimizer | Severity: | S5 (Performance) |
Version: | 5.1.25,5.1.30 | OS: | Any |
Assigned to: | Ole John Aske | CPU Architecture: | Any |
Tags: | regression |
[25 Dec 2008 8:51]
Valeriy Kravchuk
[25 Feb 2009 15:14]
Gleb Shchepa
Extracted and simplified test case
Attachment: 41740.test (application/octet-stream, text), 12.54 KiB.
[25 Feb 2009 15:16]
Gleb Shchepa
Analysis of the problem: This bug is a regression of bug #14940. As a result of this regression EXPLAIN command/JOIN::optimize phase is few times slower than before. This is probably ok because of deeper query analysis, however it chooses an execution plan with a worse cost, for example: before the regression: Last_query_cost 149.303370 after the regression: Last_query_cost 528.292652 Fortunately a workaround exists: set session optimizer_search_depth=0;
[2 Mar 2009 10:17]
Sergey Petrunya
Hi! It's very strange that we do deeper query analysis (=consider a proper superset QEPs we used to consider before) but end up choosing a plan with a worse cost! We need to find this out. Gleb, could you please investigate further, until it's clear what's the problem?
[2 Mar 2009 10:27]
Sergey Petrunya
Oops, missed the "This bug is a regression of bug #14940" part.
[18 Nov 2010 17:21]
Valeriy Kravchuk
Bug #58225 is probably a duplicate of this one. With 3 customers affected this is more like I2. Also, as set session optimizer_search_depth=0; is a partial workaround, please, consider making this (not 62) a default value (for 5.5 maybe). I'd ask for new E/R values for this change.
[16 Jan 2011 18:39]
Ole John Aske
The proposed (one-liner) fix for Bug#59326 'Greedy optimizer produce stupid query execution plans.' will fix this problem.
[16 Jan 2011 19:22]
Ole John Aske
Guess I have to explain a bit more here: The bug will be 'fixed' in the sense that an optimim execution plan is produced even with 'set session optimizer_search_depth=62'. However, producing this QEP still takes a long time (~9s w/ fix, compared with ~11s wo fix) This was tested with the 'Extracted and simplified case, from '25 Feb 2009 16:14'
[1 Feb 2011 9:44]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/130112 3552 Ole John Aske 2011-02-01 Another addendum fix related to bug#59326, and particularly its relatives/duplicates bug#41740 and bug#58225. Fixes the problem that complex queries containing a lot of EQ_REF'ed joined tables takes 'forever' to produce a query plan. The fix depends on the fact that when a table is joined by an unique key there is a 1::1 relation between the rows being joined. Assuming we have multiple such 1::1 (star-)joined relations in a sequence, without other join types inbetween. Then all of these 'eq_ref-joins' will be calculated to return the excact same #rows and having identical 'cost' (or 'read_time'). This leads to that we can append such a contigous sequence of eq_ref-joins to a partial plan in any order without affecting the total cost of the query plan. Exploring the different permutations of these eq_refs in the 'greedy' optimizations will simply be a waste of precious CPU cycles. This chain of eq_refs can further be handled as a single entity wrt. the full 'greedy' exploration of the possible join plans. This will reduce the 'N' in the O(N!) complexity of the full greedy search. The function eq_ref_extension_by_limited_search() has been implemented doing as described above. Once an EQ_REF joined table is encountered, it is invoked to append any remaining EQ_REFs to the join plan. This chain of EQ_REFs will then act like a single entity in the further exploration of possible join plans. It should be noted that best_extension_by_limited_search() will still explore the other plans starting with non-EQ_REF operations as possibly better alternatives to the EQ_REF-extended query plan. Usage of eq_ref_extension_by_limited_search() is controlled by 'optimizer_prune_level=1'. This fix also introduce the function plan_is_complete() which contains common functionality between best_extension_by_limited_search() and eq_ref_extension_by_limited_search() greedy_optimizer.test has been extensively extended with new testcases containing lots of EQ_REF's. No existing test/query plans are expected to change as result of this fix. It should only produce the 'best' plan (a lot!) faster. - Like the testcase for bug#58225 which now completes the QEP in ~0.05s in my DEBUG compiled sandbox (With 'optimizer_search_depth= 62'). This previously took 63min+42.437s :-o
[1 Feb 2011 10:27]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/130114 3553 Ole John Aske 2011-02-01 Last addendum fix related to bug#59326, and particularly its relatives/duplicates bug#41740 and bug#58225. If a filesort is required by the final result, we can include the cost for the filesort in the pruning of 'bad' plans, and possible prune the plan at an earlier stage than today. NOTE1: The 'sort_cost' is calculated with logic similar to the one in plan_is_complete() which adds the sort_cost to the best plan. NOTE2: The 'sort_cost' is calculated as '= current_record_count'. This is not entirely correct when used in the pruning logic as we do not yet #rows in the *final* result which is what we have to sort. However, it should be a safe assumption that 'final #rows' >= 'intermediat #rows'. So this prune-calculation should always be on the safe side. NOTE3: Calculating 'sort_cost= current_record_count' is a bad estimate as most sort algorithms are O(n*log(n)). This fix reduce the query compile time for the infamous bug#58225 problem further from 50ms to ~20ms
[1 Feb 2011 13:33]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/130125 3584 Ole John Aske 2011-02-01 Collection of all fixes for bug#59326 and its relatives/duplicates bug#41740 and bug#58225. Commited to the branch 'mysql-trunk-opt-bug59326' on request from QA.
[2 Feb 2011 7:51]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/130178 3587 Ole John Aske 2011-02-02 Collection of all fixes for bug#59326 and its relatives/duplicates bug#41740 and bug#58225. Commited to the branch 'mysql-trunk-opt-bug59326' on request from QA.
[16 Aug 2011 1:21]
Paul DuBois
Noted in 5.6.3 changelog. For queries with many eq_ref joins, the optimizer took excessive time to develop an execution plan.