[MDEV-9457] Poor query plan chosen for ORDER BY query by a recent 10.1 Created: 2016-01-23 Updated: 2016-02-03 Resolved: 2016-01-24 |
|
| Status: | Closed |
| Project: | MariaDB Server |
| Component/s: | Optimizer |
| Affects Version/s: | 10.1.10 |
| Fix Version/s: | 10.1.11 |
| Type: | Bug | Priority: | Major |
| Reporter: | Sergei Petrunia | Assignee: | Sergei Petrunia |
| Resolution: | Fixed | Votes: | 0 |
| Labels: | optimizer, order-by-optimization, regression | ||
| Description |
|
Discovered as part of Copying here: MariaDB 10.0:
So, in 10.0, the plan is always to use index_merge to produce one row. Actually, two rows are produced and the query finishes in 0.05 sec or less. In 10.1.10:
The same so far. Adding ORDER BY:
And the plan becomes much worse. It wants to read nearly 2M rows. Execution takes 1 min 39 sec. |
| Comments |
| Comment by Sergei Petrunia [ 2016-01-23 ] | |||||||||||||||||||||||||||
|
Copying a comment: Both versions enter test_if_cheaper_ordering() and reach this line:
In both versions:
ref_key=64 in 10.0, while in 10.1 ref_key=-1. | |||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2016-01-23 ] | |||||||||||||||||||||||||||
|
The difference in passed ref_key value is caused by these lines in 10.0:
10.1:
The change was introduced by this commit:
Here, Nirbhay and me were fixing the optimizer to work with MAX_KEY > 64, and also changed ref_key. That had an unintended consequence. | |||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2016-01-23 ] | |||||||||||||||||||||||||||
|
It is not clear what is the exact meaning of the difference in test_if_cheaper_ordering()'s behavior when invoked with ref_key=MAX_KEY or ref_key=-1. test_if_cheaper_ordering() was introduced into mysql-5.5 by Gleb Schepa in 2010. MySQL doesn't have hash join, so they don't have "hash_join_key_no=MAX_KEYS". Looking at MySQL-5.5 code. The piece of code that we're having problem with looked like this:
other parts of test_if_skip_sort_order() use ref_key=-1 to denote "no key". MAX_KEY constant is not used anywhere. The other place where test_if_cheaper_ordering called is get_index_for_order(). That function always passes ref_key=-1 as a parameter. | |||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2016-01-23 ] | |||||||||||||||||||||||||||
|
The ref_key=MAX_KEY in
was introduced in
| |||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2016-01-23 ] | |||||||||||||||||||||||||||
|
Getting back to the condition in test_if_cheaper_ordering():
We here check if we should consider switching to using a different index. Line #2 says we should do it if using the new index is cheaper. Line #1 gives some cases where we should do it regardless of what cost calculations say. My hypothesis is that the criteria are: one can question these criteria, but at least the condition looks meaningful now. Then let's look at the ref_key=-1 vs ref_key=MAX_KEY difference again. ref_key=-1 means "no index is used" while ref_key=MAX_KEY means "some index is used but not any particular index". | |||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2016-01-24 ] | |||||||||||||||||||||||||||
|
http://lists.askmonty.org/pipermail/commits/2016-January/008860.html |