[MDEV-24137] Optimizer choosing the wrong index despite of the PK showing better explain Created: 2020-11-05 Updated: 2020-12-15 |
|
| Status: | Open |
| Project: | MariaDB Server |
| Component/s: | Optimizer |
| Affects Version/s: | 10.1.43, 10.4.12, 10.4.13, 10.4.14, 10.4.15 |
| Fix Version/s: | 10.6 |
| Type: | Bug | Priority: | Major |
| Reporter: | Manuel Arostegui | Assignee: | Sergei Petrunia |
| Resolution: | Unresolved | Votes: | 0 |
| Labels: | optimizer, optimizer_trace | ||
| Environment: |
debian |
||
| Attachments: |
|
| Description |
|
We have the following table:
We have run an analyze table to refresh all the stats. The explain for it:
However, using a hint like this, changes the query plan drastically:
However, the optimizer keeps choosing the tl_namespace. This is the optimizer trace for the first and original query: https://phabricator.wikimedia.org/P13220 And the same but with the hint to use the PK: https://phabricator.wikimedia.org/P13221 At a first glance we can see the large difference on scanned rows (and run time):
And the runtime and rows if we force the PK to be used:
The query run time is way different with and without the hint:
And this is NOT doing USE (PRIMARY) and just leaving the query choosing whatever it prefers (tl_namespace);
|
| Comments |
| Comment by Sergei Petrunia [ 2020-12-06 ] | ||||||||||||||||||
|
The WHERE clause has 248 lines, the only difference is the constant in the tl_from=N The default query planUses ref acess on tl_namespace=10. Range optimizer didn't construct any potential query plans. The query plan with force indexuses range plan over all 3 key parts of the primary key:
which is basically the whole WHERE clause. 248 lines * 10 elements in the in-list gives 2480 ranges. Optimizer trace confirms this. | ||||||||||||||||||
| Comment by Sergei Petrunia [ 2020-12-06 ] | ||||||||||||||||||
|
Indeed, the range optimizer is hitting MAX_SEL_ARGS limitation. After the primary get_mm_tree call:
| ||||||||||||||||||
| Comment by Sergei Petrunia [ 2020-12-06 ] | ||||||||||||||||||
|
Increased the MAX_SEL_ARGS limit 10x . The query would consume this many:
| ||||||||||||||||||
| Comment by Sergei Petrunia [ 2020-12-06 ] | ||||||||||||||||||
|
The query doesn't have restrictions on the first part of the key tl_backlinks_namespace. I've dropped it to make sure it's not interfering.
Re-running the explain and noting the alloced_sel_args after the get_mm_tree:
| ||||||||||||||||||
| Comment by Sergei Petrunia [ 2020-12-06 ] | ||||||||||||||||||
|
That is, the code that constructs ranges for a specific index is not the issue. The high usage is caused by the code that combines scans on multiple indexes. | ||||||||||||||||||
| Comment by Sergei Petrunia [ 2020-12-06 ] | ||||||||||||||||||
|
Indeed, the code in tree_or does the cloning in order to construct index_merge:
must_be_ored=false, because indexes primary and tl_namespace are not infixes of each other. Because of that,
Then, this code in the main per-key key_or() loop copies the trees:
copying the trees is fully justified, because tree_or will later construct a SEL_IMERGE from them. but if we have an N-way OR condition, with each OR-branch producing one range, the number of copying will be:
ranges. | ||||||||||||||||||
| Comment by Sergei Petrunia [ 2020-12-12 ] | ||||||||||||||||||
|
A patch for printing the generated trees: xpl.diff This covers only the first rows of the query:
Apparently the optimizer is building a lot of options to construct index_merge plans (including a 3-way index_merge even when there are two indexes!). It is not clear for me how to fix this, though. |