Skip to content

Commit

Permalink
MDEV-28929: Plan selection takes forever with MDEV-28852 ...
Browse files Browse the repository at this point in the history
Part #2: Extend heuristic pruning to use multiple tables as the
"Model tables".

Before the patch, heuristic pruning uses only one "Model table":
The table which had the best cost AND record became the "Model table".
After that, if a table's cost and record were both worse than
those of the Model Table, the table would be pruned away.

This didn't work well when the first table (the optimizer sorts them
by record_count) had low record_count but relatively high cost: nothing
could be pruned afterwards.

The patch adds the two additional "Model tables": one with the least
cost and the other with the least record_count.
(In both cases, a table can be pruned away if BOTH its cost and
record_count are worse than those of a Model table)

The new pruning is active when the number of tables to consider for
the prefix is higher than @@optimizer_extra_pruning_depth.

One can see the new pruning in the Optimizer Trace as
- "pruned_by_heuristic":"min_record_count", or
- "pruned_by_heuristic":"min_read_time".
Old heuristic pruning shows as "pruned_by_heuristic":1.
  • Loading branch information
spetrunia committed Jul 26, 2022
1 parent afadd58 commit 8c2faad
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 178 deletions.
5 changes: 5 additions & 0 deletions mysql-test/main/mysqld--help.result
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,10 @@ The following specify which files/extra groups are read (specified before remain
max_connections*5 or max_connections + table_cache*2
(whichever is larger) number of file descriptors
(Automatically configured unless set explicitly)
--optimizer-extra-pruning-depth=#
If the optimizer needs to enumerate join prefix of this
size or larger, then it will try agressively prune away
the search space.
--optimizer-max-sel-arg-weight=#
The maximum weight of the SEL_ARG graph. Set to 0 for no
limit
Expand Down Expand Up @@ -1662,6 +1666,7 @@ old-alter-table DEFAULT
old-mode UTF8_IS_UTF8MB3
old-passwords FALSE
old-style-user-limits FALSE
optimizer-extra-pruning-depth 8
optimizer-max-sel-arg-weight 32000
optimizer-prune-level 2
optimizer-search-depth 62
Expand Down
162 changes: 2 additions & 160 deletions mysql-test/main/opt_trace.result
Original file line number Diff line number Diff line change
Expand Up @@ -6035,86 +6035,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
"rows_for_plan": 729,
"cost_for_plan": 176.0410156,
"semijoin_strategy_choice": [],
"rest_of_plan": [
{
"plan_prefix": [
"t_outer_1",
"t_outer_2",
"t_inner_1",
"t_inner_3"
],
"get_costs_for_tables": [
{
"best_access_path": {
"table": "t_inner_4",
"considered_access_paths": [
{
"access_type": "scan",
"resulting_rows": 3,
"cost": 2.005126953,
"chosen": true
}
],
"chosen_access_method": {
"type": "scan",
"records": 3,
"cost": 2.005126953,
"uses_join_buffering": true
}
}
},
{
"best_access_path": {
"table": "t_inner_2",
"considered_access_paths": [
{
"access_type": "scan",
"resulting_rows": 9,
"cost": 2.015380859,
"chosen": true
}
],
"chosen_access_method": {
"type": "scan",
"records": 9,
"cost": 2.015380859,
"uses_join_buffering": true
}
}
}
]
},
{
"plan_prefix": [
"t_outer_1",
"t_outer_2",
"t_inner_1",
"t_inner_3"
],
"table": "t_inner_2",
"rows_for_plan": 6561,
"cost_for_plan": 1490.256396,
"semijoin_strategy_choice": [],
"pruned_by_cost": true,
"current_cost": 1490.256396,
"best_cost": 568.8615234
},
{
"plan_prefix": [
"t_outer_1",
"t_outer_2",
"t_inner_1",
"t_inner_3"
],
"table": "t_inner_4",
"rows_for_plan": 2187,
"cost_for_plan": 615.4461426,
"semijoin_strategy_choice": [],
"pruned_by_cost": true,
"current_cost": 615.4461426,
"best_cost": 568.8615234
}
]
"pruned_by_heuristic": "min_read_time"
}
]
},
Expand Down Expand Up @@ -6596,86 +6517,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
"rows_for_plan": 729,
"cost_for_plan": 172.4410156,
"semijoin_strategy_choice": [],
"rest_of_plan": [
{
"plan_prefix": [
"t_outer_1",
"t_inner_1",
"t_outer_2",
"t_inner_3"
],
"get_costs_for_tables": [
{
"best_access_path": {
"table": "t_inner_4",
"considered_access_paths": [
{
"access_type": "scan",
"resulting_rows": 3,
"cost": 2.005126953,
"chosen": true
}
],
"chosen_access_method": {
"type": "scan",
"records": 3,
"cost": 2.005126953,
"uses_join_buffering": true
}
}
},
{
"best_access_path": {
"table": "t_inner_2",
"considered_access_paths": [
{
"access_type": "scan",
"resulting_rows": 9,
"cost": 2.015380859,
"chosen": true
}
],
"chosen_access_method": {
"type": "scan",
"records": 9,
"cost": 2.015380859,
"uses_join_buffering": true
}
}
}
]
},
{
"plan_prefix": [
"t_outer_1",
"t_inner_1",
"t_outer_2",
"t_inner_3"
],
"table": "t_inner_2",
"rows_for_plan": 6561,
"cost_for_plan": 1486.656396,
"semijoin_strategy_choice": [],
"pruned_by_cost": true,
"current_cost": 1486.656396,
"best_cost": 565.2615234
},
{
"plan_prefix": [
"t_outer_1",
"t_inner_1",
"t_outer_2",
"t_inner_3"
],
"table": "t_inner_4",
"rows_for_plan": 2187,
"cost_for_plan": 611.8461426,
"semijoin_strategy_choice": [],
"pruned_by_cost": true,
"current_cost": 611.8461426,
"best_cost": 565.2615234
}
]
"pruned_by_heuristic": "min_read_time"
}
]
},
Expand Down
10 changes: 10 additions & 0 deletions mysql-test/suite/sys_vars/r/sysvars_server_embedded.result
Original file line number Diff line number Diff line change
Expand Up @@ -2252,6 +2252,16 @@ NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY YES
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_EXTRA_PRUNING_DEPTH
VARIABLE_SCOPE SESSION
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT If the optimizer needs to enumerate join prefix of this size or larger, then it will try agressively prune away the search space.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 62
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_MAX_SEL_ARG_WEIGHT
VARIABLE_SCOPE SESSION
VARIABLE_TYPE BIGINT UNSIGNED
Expand Down
10 changes: 10 additions & 0 deletions mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
Original file line number Diff line number Diff line change
Expand Up @@ -2422,6 +2422,16 @@ NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY YES
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_EXTRA_PRUNING_DEPTH
VARIABLE_SCOPE SESSION
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT If the optimizer needs to enumerate join prefix of this size or larger, then it will try agressively prune away the search space.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 62
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_MAX_SEL_ARG_WEIGHT
VARIABLE_SCOPE SESSION
VARIABLE_TYPE BIGINT UNSIGNED
Expand Down
1 change: 1 addition & 0 deletions sql/sql_class.h
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,7 @@ typedef struct system_variables
ulong net_retry_count;
ulong net_wait_timeout;
ulong net_write_timeout;
ulong optimizer_extra_pruning_depth;
ulong optimizer_prune_level;
ulong optimizer_search_depth;
ulong optimizer_selectivity_sampling_limit;
Expand Down
Loading

0 comments on commit 8c2faad

Please sign in to comment.