[MDEV-20364] Optimizer chooses wrong access access method with LooseScan semi-join strategy Created: 2019-08-16 Updated: 2020-08-25 Resolved: 2019-09-16 |
|
| Status: | Closed |
| Project: | MariaDB Server |
| Component/s: | Optimizer |
| Affects Version/s: | 10.4 |
| Fix Version/s: | N/A |
| Type: | Bug | Priority: | Major |
| Reporter: | Sergei Petrunia | Assignee: | Sergei Petrunia |
| Resolution: | Not a Bug | Votes: | 0 |
| Labels: | None | ||
| Issue Links: |
|
||||||||
| Description |
|
The optimizer may choose poor (expensive) access methods to be used together with LooseScan semi-join strategy. The original example was observed at a customer, and we don't have access to the dataset. I've also found this example in subselect3.result. I'm not sure if it is the same issue, but this gives an example to study:
Why does LooseScan use type=index? There is a possible range access on index kp1. It is certainly better than the full table scan. Running the subquery standalone uses the select:
|
| Comments |
| Comment by Sergei Petrunia [ 2019-09-12 ] | |||||||||||||||||||||||||
|
For the testcase in the report, the optimizer no longer chooses LooseScan after fix for | |||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2019-09-13 ] | |||||||||||||||||||||||||
|
... But when I debug the code, I can still see suspicious places. I need a bit more time. | |||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2019-09-15 ] | |||||||||||||||||||||||||
|
Testcase for debugging: https://gist.github.com/spetrunia/32b45da17c5da3a71fa89e44276e69c0 The suspicious place was this code in fix_semijoin_strategies_for_picked_join_order:
loose_scan_pos is filled by Loose_scan_opt::save_to_position() which sets the member variables describing the table access, as well as some of the members of loosescan_picker :
| |||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2019-09-15 ] | |||||||||||||||||||||||||
|
... and this way, join->best_positions[i].key will point to the index required by the Loose Scan strategy. No issue here. loosescan_picker.loosescan_key is still used by the code in sub_select(), because full index scan and ref access do not have a single place where one could get index-nr from. | |||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2019-09-15 ] | |||||||||||||||||||||||||
|
The member variables prefix_record_count and sj_strategy are not set in save_to_position(). The sj_strategy is set in fix_semijoin_strategies_for_picked_join_order(), below the best_access_path() loop:
prefix_record_count is never set, so we end up with it being unset in join->best_positions[ first_loose_scan_table]. It looks like the member is never used after the fix_semijoin_strategies_for_picked_join_order call, though. |