在我們調優MySQL的SQL時候,通常使用三種工具進行查看sql執行的效率,explain、profile、optimizer_trace。前兩個經常被人使用,由於第三個難度較大,大家使用的較少,下面簡單說下如何使用。
opitimizer_trace的使用:
# 開啟跟蹤,默認是關閉的
SET optimizer_trace="enabled=on";
#執行你的sql語句
select ....
#查看trace信息
SELECT * FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
# 執行完你需要的sql語句就可以關閉trace了
SET optimizer_trace="enabled=off";
支持的trace語句有:
1.SELECT;
2.INSERT or REPLACE (with VALUES or SELECT);
3.UPDATE/DELETE and their multi-table variants;
4.all the previous ones prefixed by EXPLAIN;
5.SET (unless it manipulates the optimizer_trace system variable);
6.DO;
7.DECLARE/CASE/IF/RETURN (stored routines language elements);
8.CALL.
如下這個語句可以把結果插入到一個文件里:
SELECT TRACE INTO DUMPFILE <filename> FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
在mysqld里進行設置相關參數:
A brief overview from "mysqld --verbose --help":
--optimizer-trace=name
Controls tracing of the Optimizer:
--optimizer-trace-features=name
Enables/disables tracing of selected features of the
Optimizer:
optimizer_trace_features=option=val[,option=val...],
where option is one of {greedy_search, range_optimizer,
dynamic_range, repeated_subselect} and val is one of {on,
off, default}
--optimizer-trace-limit=#
Maximum number of shown optimizer traces
--optimizer-trace-max-mem-size=#
Maximum allowed cumulated size of stored optimizer traces
--optimizer-trace-offset=#
Offset of first optimizer trace to show; see manual
--end-markers-in-json=#
In JSON output ("EXPLAIN FORMAT=JSON" and optimizer
trace), if set to 1, repeats the structure's key (if it
has one) near the closing bracket
具體跟蹤的json格式的信息:
select * from test1,test2 where test1.id=test2.id and test1.id>4999900 | {
"steps": [
{
"join_preparation": { --連接准備
"select#": 1, --join准備的第一步
"steps": [ --解析成編號,解析數據庫和表
{
"expanded_query": "/* select#1 */ select `test1`.`id` AS `id`,`test1`.`k` AS `k`,`test1`.`c` AS `c`,`test1`.`pad` AS `pad`,`test2`.`id` AS `id`,`test2`.`k` AS `k`,`test2`.`c` AS `c`,`test2`.`pad` AS `pad` from `test1` join `test2` where ((`test1`.`id` = `test2`.`id`) and (`test1`.`id` > 4999900))"
}
]
}
},
{
"join_optimization": { --join優化
"select#": 1,
"steps": [
{
"condition_processing": { --where條件
"condition": "WHERE",
"original_condition": "((`test1`.`id` = `test2`.`id`) and (`test1`.`id` > 4999900))",
"steps": [ --優化的步驟
{
"transformation": "equality_propagation", --等值優化
"resulting_condition": "((`test1`.`id` > 4999900) and multiple equal(`test1`.`id`, `test2`.`id`))" --把test.id>4999900放到前面,test1.id=test2.id使用多等值連接
},
{
"transformation": "constant_propagation", --常量優化
"resulting_condition": "((`test1`.`id` > 4999900) and multiple equal(`test1`.`id`, `test2`.`id`))"
},
{
"transformation": "trivial_condition_removal", --瑣碎的條件排除
"resulting_condition": "((`test1`.`id` > 4999900) and multiple equal(`test1`.`id`, `test2`.`id`))"
}
]
}
},
{
"table_dependencies": [ --表依賴
{
"table": "`test1`", --表名
"row_may_be_null": false, --是否有null值,flase是沒有
"map_bit": 0,
"depends_on_map_bits": [
]
},
{
"table": "`test2`",
"row_may_be_null": false,
"map_bit": 1,
"depends_on_map_bits": [
]
}
]
},
{
"ref_optimizer_key_uses": [ --相關優化索引使用
{
"table": "`test1`",
"field": "id", --索引字段
"equals": "`test2`.`id`", --連接的等值字段
"null_rejecting": false
},
{
"table": "`test2`",
"field": "id",
"equals": "`test1`.`id`",
"null_rejecting": false
}
]
},
{
"rows_estimation": [ --行評估
{
"table": "`test1`",
"range_analysis": { --范圍分析
"table_scan": {
"rows": 4804854, --4804854行數據
"cost": 1.03e6 --花費1.03e6
},
"potential_range_indices": [ --可能的范圍指數
{
"index": "PRIMARY",
"usable": true, --可使用的索引
"key_parts": [
"id"
] --可使用的索引字段
},
{
"index": "k_1",
"usable": false, --不能使用的索引
"cause": "not_applicable" --不被應用
}
],
"setup_range_conditions": [ --設置范圍條件
],
"group_index_range": { --組范圍索引
"chosen": false, --不選擇的
"cause": "not_single_table" --goup by不是一個表的,所以不選擇
},
"analyzing_range_alternatives": { --分析每個索引做范圍掃描的花費
"range_scan_alternatives": [ --范圍掃描花費
{
"index": "PRIMARY",
"ranges": [
"4999900 < id"
],
"index_dives_for_eq_ranges": true, --索引驅動等值范圍掃描
"rowid_ordered": true, --rowid是順序的
"using_mrr": false, --不能使用mrr,因為是主鍵
"index_only": false,
"rows": 99, --過濾出來99行
"cost": 21.434, --花費21.434
"chosen": true --這個索引被選擇選擇
}
],
"analyzing_roworder_intersect": { --分析執行順序階段
"usable": false, --不可使用
"cause": "too_few_roworder_scans" --少數的執行順序掃描
}
},
"chosen_range_access_summary": { --選擇范圍訪問概述
"range_access_plan": {
"type": "range_scan",
"index": "PRIMARY",
"rows": 99,
"ranges": [
"4999900 < id"
]
},
"rows_for_plan": 99,
"cost_for_plan": 21.434,
"chosen": true
}
}
},
{
"table": "`test2`",
"range_analysis": {
"table_scan": {
"rows": 4804854,
"cost": 1.03e6
},
"potential_range_indices": [
{
"index": "PRIMARY",
"usable": true,
"key_parts": [
"id"
]
},
{
"index": "k_2",
"usable": false,
"cause": "not_applicable"
}
],
"setup_range_conditions": [
],
"group_index_range": {
"chosen": false,
"cause": "not_single_table"
},
"analyzing_range_alternatives": {
"range_scan_alternatives": [
{
"index": "PRIMARY",
"ranges": [
"4999900 < id"
],
"index_dives_for_eq_ranges": true,
"rowid_ordered": true,
"using_mrr": false,
"index_only": false,
"rows": 99,
"cost": 21.433,
"chosen": true
}
],
"analyzing_roworder_intersect": {
"usable": false,
"cause": "too_few_roworder_scans"
}
},
"chosen_range_access_summary": {
"range_access_plan": {
"type": "range_scan",
"index": "PRIMARY",
"rows": 99,
"ranges": [
"4999900 < id"
]
},
"rows_for_plan": 99,
"cost_for_plan": 21.433,
"chosen": true
}
}
}
]
},
{
"considered_execution_plans": [ --決定執行計划
{
"plan_prefix": [ --計划前
],
"table": "`test1`", --test1表的執行計划
"best_access_path": { --最好的訪問路徑
"considered_access_paths": [ --決定的訪問路徑
{
"access_type": "ref", --訪問類型是ref
"index": "PRIMARY", --使用的索引是主鍵
"usable": false,
"chosen": false
},
{
"access_type": "range",
"rows": 99,
"cost": 41.234,
"chosen": true
}
]
},
"cost_for_plan": 41.234,
"rows_for_plan": 99,
"rest_of_plan": [
{
"plan_prefix": [
"`test1`"
],
"table": "`test2`",
"best_access_path": {
"considered_access_paths": [
{
"access_type": "ref",
"index": "PRIMARY",
"rows": 1,
"cost": 99.2,
"chosen": true
},
{
"access_type": "range",
"cause": "heuristic_index_cheaper",
"chosen": false
}
]
},
"cost_for_plan": 160.03,
"rows_for_plan": 99,
"chosen": true
}
]
},
{
"plan_prefix": [
],
"table": "`test2`",
"best_access_path": {
"considered_access_paths": [
{
"access_type": "ref",
"index": "PRIMARY",
"usable": false,
"chosen": false
},
{
"access_type": "range",
"rows": 99,
"cost": 41.233,
"chosen": true
}
]
},
"cost_for_plan": 41.233,
"rows_for_plan": 99,
"rest_of_plan": [
{
"plan_prefix": [
"`test2`"
],
"table": "`test1`",
"best_access_path": {
"considered_access_paths": [
{
"access_type": "ref",
"index": "PRIMARY",
"rows": 1,
"cost": 99.2,
"chosen": true
},
{
"access_type": "range",
"cause": "heuristic_index_cheaper",
"chosen": false
}
]
},
"cost_for_plan": 160.03,
"rows_for_plan": 99,
"pruned_by_cost": true
}
]
}
]
},
{
"attaching_conditions_to_tables": {
"original_condition": "((`test2`.`id` = `test1`.`id`) and (`test1`.`id` > 4999900))",
"attached_conditions_computation": [
],
"attached_conditions_summary": [
{
"table": "`test1`",
"attached": "(`test1`.`id` > 4999900)"
},
{
"table": "`test2`",
"attached": null
}
]
}
},
{
"refine_plan": [
{
"table": "`test1`",
"access_type": "range"
},
{
"table": "`test2`"
}
]
}
]
}
},
{
"join_execution": {
"select#": 1,
"steps": [
]
}
}
]
}