1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

MDEV-6111 Optimizer Trace

This task involves the implementation for the optimizer trace.

This feature produces a trace for any SELECT/UPDATE/DELETE/,
which contains information about decisions taken by the optimizer during
the optimization phase (choice of table access method, various costs,
transformations, etc). This feature would help to tell why some decisions were
taken by the optimizer and why some were rejected.

Trace is session-local, controlled by the @@optimizer_trace variable.
To enable optimizer trace we need to write:
   set @@optimizer_trace variable= 'enabled=on';

To display the trace one can run:
   SELECT trace FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;

This task also involves:
    MDEV-18489: Limit the memory used by the optimizer trace
    introduces a switch optimizer_trace_max_mem_size which limits
    the memory used by the optimizer trace. This was implemented by
    Sergei Petrunia.
This commit is contained in:
Varun Gupta
2019-02-13 11:22:16 +05:30
parent 6b979416e0
commit be8709eb7b
47 changed files with 8227 additions and 622 deletions

View File

@ -0,0 +1,249 @@
set @tmp_opt_switch= @@optimizer_switch;
set optimizer_switch='index_merge_sort_intersection=on';
set optimizer_trace='enabled=on';
create table t0 (a int);
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
create table t1 (a int, b int, c int, filler char(100),
key(a), key(b), key(c));
insert into t1 select
A.a * B.a*10 + C.a*100,
A.a * B.a*10 + C.a*100,
A.a,
'filler'
from t0 A, t0 B, t0 C;
This should use union:
explain select * from t1 where a=1 or b=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge a,b a,b 5,5 NULL 2 Using union(a,b); Using where
select * from information_schema.OPTIMIZER_TRACE;
QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
explain select * from t1 where a=1 or b=1 {
"steps": [
{
"join_preparation": {
"select_id": 1,
"steps": [
{
"expanded_query": "select `t1`.`a` AS `a`,`t1`.`b` AS `b`,`t1`.`c` AS `c`,`t1`.`filler` AS `filler` from `t1` where `t1`.`a` = 1 or `t1`.`b` = 1"
}
]
}
},
{
"join_optimization": {
"select_id": 1,
"steps": [
{
"condition_processing": {
"condition": "WHERE",
"original_condition": "t1.a = 1 or t1.b = 1",
"steps": [
{
"transformation": "equality_propagation",
"resulting_condition": "multiple equal(1, t1.a) or multiple equal(1, t1.b)"
},
{
"transformation": "constant_propagation",
"resulting_condition": "multiple equal(1, t1.a) or multiple equal(1, t1.b)"
},
{
"transformation": "trivial_condition_removal",
"resulting_condition": "multiple equal(1, t1.a) or multiple equal(1, t1.b)"
}
]
}
},
{
"table_dependencies": [
{
"table": "t1",
"row_may_be_null": false,
"map_bit": 0,
"depends_on_map_bits": []
}
]
},
{
"ref_optimizer_key_uses": []
},
{
"rows_estimation": [
{
"table": "t1",
"range_analysis": {
"table_scan": {
"rows": 1000,
"cost": 231.69
},
"potential_range_indexes": [
{
"index": "a",
"usable": true,
"key_parts": ["a"]
},
{
"index": "b",
"usable": true,
"key_parts": ["b"]
},
{
"index": "c",
"usable": false,
"cause": "not applicable"
}
],
"setup_range_conditions": [],
"group_index_range": {
"chosen": false,
"cause": "no group by or distinct"
},
"analyzing_range_alternatives": {
"range_scan_alternatives": [],
"analyzing_roworder_intersect": {
"cause": "too few roworder scans"
},
"analyzing_sort_intersect": {},
"analyzing_index_merge_union": [
{
"indexes_to_merge": [
{
"range_scan_alternatives": [
{
"index": "a",
"ranges": ["1 <= a <= 1"],
"rowid_ordered": true,
"using_mrr": false,
"index_only": true,
"rows": 1,
"cost": 2.21,
"chosen": true
}
],
"index_to_merge": "a",
"cumulated_cost": 2.21
},
{
"range_scan_alternatives": [
{
"index": "b",
"ranges": ["1 <= b <= 1"],
"rowid_ordered": true,
"using_mrr": false,
"index_only": true,
"rows": 1,
"cost": 2.21,
"chosen": true
}
],
"index_to_merge": "b",
"cumulated_cost": 4.42
}
],
"cost_of_reading_ranges": 4.42,
"use_roworder_union": true,
"cause": "always cheaper than non roworder retrieval",
"analyzing_roworder_scans": [
{
"type": "range_scan",
"index": "a",
"rows": 1,
"ranges": ["1 <= a <= 1"],
"analyzing_roworder_intersect": {
"cause": "too few roworder scans"
}
},
{
"type": "range_scan",
"index": "b",
"rows": 1,
"ranges": ["1 <= b <= 1"],
"analyzing_roworder_intersect": {
"cause": "too few roworder scans"
}
}
],
"index_roworder_union_cost": 6.2137,
"members": 2,
"chosen": true
}
]
},
"chosen_range_access_summary": {
"range_access_plan": {
"type": "index_roworder_union",
"union_of": [
{
"type": "range_scan",
"index": "a",
"rows": 1,
"ranges": ["1 <= a <= 1"]
},
{
"type": "range_scan",
"index": "b",
"rows": 1,
"ranges": ["1 <= b <= 1"]
}
]
},
"rows_for_plan": 2,
"cost_for_plan": 6.2137,
"chosen": true
}
}
},
{
"selectivity_for_indexes": [],
"selectivity_for_columns": []
}
]
},
{
"execution_plan_for_potential_materialization": {
"steps": []
}
},
{
"considered_execution_plans": [
{
"plan_prefix": [],
"table": "t1",
"best_access_path": {
"considered_access_paths": [
{
"access_type": "range",
"resulting_rows": 2,
"cost": 6.2137,
"chosen": true
}
]
}
}
]
},
{
"attaching_conditions_to_tables": {
"original_condition": "t1.a = 1 or t1.b = 1",
"attached_conditions_computation": [],
"attached_conditions_summary": [
{
"table": "t1",
"attached": "t1.a = 1 or t1.b = 1"
}
]
}
}
]
}
},
{
"join_execution": {
"select_id": 1,
"steps": []
}
}
]
} 0 0
drop table t0,t1;
set optimizer_trace="enabled=off";
set @@optimizer_switch= @tmp_opt_switch;