[MDEV-8989] ORDER BY optimizer ignores equality propagation Created: 2015-10-22 Updated: 2016-09-24 Resolved: 2016-06-03 |
|
| Status: | Closed |
| Project: | MariaDB Server |
| Component/s: | Optimizer |
| Affects Version/s: | 10.1 |
| Fix Version/s: | 10.1.15 |
| Type: | Bug | Priority: | Critical |
| Reporter: | Sergei Petrunia | Assignee: | Sergei Petrunia |
| Resolution: | Fixed | Votes: | 1 |
| Labels: | SUSE, order-by-optimization | ||
| Issue Links: |
|
||||||||
| Sprint: | 10.1.10, 10.2.0-4, 10.1.11, 10.1.12, 10.2.1-1, 10.2.1-3, 10.2.1-4, 10.2.1-5 | ||||||||
| Description |
|
Re-filing this here from https://bugzilla.suse.com/show_bug.cgi?id=949520 : Consider a query:
The join optimizer picks the join order of sa, su.
Good so far. Now, let's try to change ORDER BY sa.id into ORDER BY su.id. The query However, there is:
ORDER BY optimizer no longer recognizes that index on sa.id produces the desired ordering. |
| Comments |
| Comment by Sergei Petrunia [ 2015-10-22 ] | |||||||||||||||||||||||||||||||||||||||||
|
The problem seems to be much easier than MDEV-4205 or MDEV-8306. The presence of sa.id=su.id equality (and indexes on both of these columns) means that either join order is good for optimizing ORDER BY ... LIMIT. | |||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2015-10-22 ] | |||||||||||||||||||||||||||||||||||||||||
|
Debugging, I see that the opportunity is missed in test_if_skip_sort_order(). The optimizer calls build_equal_items() and substitute_for_best_equal() for HAVING, WHERE, and ON expressions but not for ORDER BY. I've tried adding substitute_for_best_equal() call
but this didn't work. substitute_for_best_equal relies on build_equal_items() to have been done before, e.g. it sets Item_field::item_equal which substitute_for_best_equal() relies on. We don't want to call build_equal_items() for ORDER BY expression - there is no point in building equality sets, etc. There needs to be a simpler function. | |||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2015-10-22 ] | |||||||||||||||||||||||||||||||||||||||||
|
Probably need to use Item_field::find_item_equal. (Q: does this function check that it is really ok to do the substitution? considering possible different datatypes/collations, etc?) Also would like to look at this: there are actually two kinds of equality substitution. The one I'm talking about here is where t1.col1 is substituted for t2.col2 in arbitrary context. There is also substitution where t1.col1 is substituted for t2.col2 only when used in range-style comparisons, e.g. "t1.col1 < foo" is substuted with "t2.col2 < foo" while func(t1.col1) is not substituted with func(t2.col2). I can't find it the code. WIll need to discuss with other team members. | |||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2015-10-22 ] | |||||||||||||||||||||||||||||||||||||||||
|
Yet another question: can substitute ORDER::item member with something else? What happens if this is a PS and we will need another execution? | |||||||||||||||||||||||||||||||||||||||||
| Comment by Michal Koutny [ 2015-11-19 ] | |||||||||||||||||||||||||||||||||||||||||
|
Hi Sergei. What is progress with this issue? Did you discussed the suggested solutions within your team (I hope the the questions didn't fail to reach them)? Thanks, for any update. | |||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2015-12-21 ] | |||||||||||||||||||||||||||||||||||||||||
|
Investigation notes: field substitution in ORDER BY field should be done before We should use multi-equalities from WHERE's top level. They are in I cannot yet understand what is the right way to do substitutions.
initially
, but tthen setup_order()/find_item_order_in_list() changes order->item to point into ref_pointer_array. If the ORDER BY item is not present in ref_pointer_array, it adds it there, and also adds it into all_fields:
| |||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2015-12-21 ] | |||||||||||||||||||||||||||||||||||||||||
|
Notes from discussion with sanja: ORDER BY elements are put into ref_pointer_array because the optimizer It should be ok to replace the element in ref_pointer_array and We can tell whether this happened by checking ORDER::in_field_list. If we are about to replace t1.colX with t2.colY in the ORDER BY clause,
then we should add t2.colY into these structures, just like This is safe to do. There is an upper bound on the number of elements in For prepared statements, ORDER BY list is restored on every execution (check
| |||||||||||||||||||||||||||||||||||||||||
| Comment by Michal Koutny [ 2016-01-07 ] | |||||||||||||||||||||||||||||||||||||||||
|
Hi, I'm just wondering how close/far is this to getting solved? It seemed rather promising to me previously. Thanks. | |||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2016-01-14 ] | |||||||||||||||||||||||||||||||||||||||||
|
Werkov, I now have a "candidate" patch. It needs to be tested and it needs to pass a code review. I'll be posting updates here. | |||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2016-01-14 ] | |||||||||||||||||||||||||||||||||||||||||
|
When implementing the fix, I've hit test failures like this:
Investigation shows that ref access uses an incorrect key when constructing key lookup value:
store_key_item::copy_inner calls
which does:
That is it copies data from Item_field::result_field. Normally, Item_field objects have result_field==field, and it doesn't matter. However, my patch puts the Item_field object into GROUP BY clause. create_tmp_table() sets item_field->result_field to point into the GROUP-BY temporary table. As a result, we get key values from the temporary table. This is wrong, because we're still at doing-the-join phase of the query and should get the data from Item_field->field. | |||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2016-01-14 ] | |||||||||||||||||||||||||||||||||||||||||
|
Fix for the above problem: https://gist.github.com/spetrunia/3edfdd131c103f538030 . sanja, this is what we've discussed on the optimizer call. Can you review it please? | |||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2016-01-14 ] | |||||||||||||||||||||||||||||||||||||||||
|
The first version of the patch: http://lists.askmonty.org/pipermail/commits/2016-January/008826.html . igor questioned its approach on the optimizer call, will need to catch with him to discuss it. | |||||||||||||||||||||||||||||||||||||||||
| Comment by Oleksandr Byelkin [ 2016-01-15 ] | |||||||||||||||||||||||||||||||||||||||||
|
OK to push. | |||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2016-01-25 ] | |||||||||||||||||||||||||||||||||||||||||
|
Following suggestion by igor, started to develop a fix that makes use of multiple equalities without doing the substitution: https://gist.github.com/spetrunia/8dd6f05759beb06911f1 . The fix passes the bug example. I suspect, it doesnt pass in the cases where Using temporary; Using filesort was changed into Using filesort. Need to discuss this with Igor again. | |||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2016-01-25 ] | |||||||||||||||||||||||||||||||||||||||||
|
Discussion results
| |||||||||||||||||||||||||||||||||||||||||
| Comment by Michal Koutny [ 2016-02-05 ] | |||||||||||||||||||||||||||||||||||||||||
|
Hello. Will the patch from this comment be eventually merged wrt to the following comment? Or is it still waiting for some refactoring? Thanks. | |||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2016-02-21 ] | |||||||||||||||||||||||||||||||||||||||||
|
http://lists.askmonty.org/pipermail/commits/2016-February/009026.html . This is the second variant of the fix. igor, can you please review? | |||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2016-02-21 ] | |||||||||||||||||||||||||||||||||||||||||
|
Werkov, Sanja' s approval was for the patch https://gist.github.com/spetrunia/3edfdd131c103f538030. It is just a pre-requisite Now, I've committed the second variant. It will need to pass the review, first. | |||||||||||||||||||||||||||||||||||||||||
| Comment by Michal Koutny [ 2016-03-10 ] | |||||||||||||||||||||||||||||||||||||||||
|
Sergei, thanks for explanation. Do you have any feedback on the second variant? | |||||||||||||||||||||||||||||||||||||||||
| Comment by Michal Koutny [ 2016-03-24 ] | |||||||||||||||||||||||||||||||||||||||||
|
I see the bug is still Stalled and it's unclear what is it blocked on. Originally it was estimated for 10.1.10 and 10.1.12 is out now | |||||||||||||||||||||||||||||||||||||||||
| Comment by Michal Koutny [ 2016-05-05 ] | |||||||||||||||||||||||||||||||||||||||||
|
Hi, in e-mail from Sergei I got on 2016-04-11, today was mentioned as the latest day for this to resolve. However, I can only see the bug got assigned to another sprint. Is there any progress not visible here? What is the next step? Can this please get more attention? Thanks. | |||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2016-05-05 ] | |||||||||||||||||||||||||||||||||||||||||
|
Hi Michal, | |||||||||||||||||||||||||||||||||||||||||
| Comment by Michal Koutny [ 2016-05-06 ] | |||||||||||||||||||||||||||||||||||||||||
|
Great, thanks for update. Do you have time estimate, will it fit into the current sprint (10.2.1-1)? | |||||||||||||||||||||||||||||||||||||||||
| Comment by Michal Koutny [ 2016-05-18 ] | |||||||||||||||||||||||||||||||||||||||||
|
Oh, me again. What's the state of this bug? AFAICS it's not included in the current sprint, what are plans then? | |||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2016-05-23 ] | |||||||||||||||||||||||||||||||||||||||||
|
Hi Michal. The bug was included in the sprint (and was in the works regardless of that). | |||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2016-05-23 ] | |||||||||||||||||||||||||||||||||||||||||
|
Status update: During the review igor has mentioned on the phone call that propagate_equal_fields call should be used. He has mentioned that this will resolve a possible issue with VIEWs. I'm now trying to make sense of this comment. | |||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2016-05-23 ] | |||||||||||||||||||||||||||||||||||||||||
|
The mentioned issue is described in a comment to this commit: https://github.com/MariaDB/server/commit/8d9dd21d85e257051b45b2f779dcd9bf696bf9e1
| |||||||||||||||||||||||||||||||||||||||||
| Comment by Michal Koutny [ 2016-05-24 ] | |||||||||||||||||||||||||||||||||||||||||
|
Thanks for update. Hopefully use of propagate_equal_fields will make the patch eventually acceptable. | |||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2016-05-25 ] | |||||||||||||||||||||||||||||||||||||||||
|
Status update:
| |||||||||||||||||||||||||||||||||||||||||
| Comment by Elena Stepanova [ 2016-05-25 ] | |||||||||||||||||||||||||||||||||||||||||
|
Testing is in progress. So far no failures revealed, but it's not finished yet. | |||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2016-05-26 ] | |||||||||||||||||||||||||||||||||||||||||
|
Update:
| |||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2016-06-03 ] | |||||||||||||||||||||||||||||||||||||||||
|
The patch was pushed into MariaDB-10.1.
The fix will be enabled by default in MariaDB 10.2 | |||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2016-06-03 ] | |||||||||||||||||||||||||||||||||||||||||
|
We will be able to enable the fix by default in 10.2 after it has been merged to 10.2. Filed |