root@D0DCS 15:17:24 [jing]> show create table t1\G;
*************************** 1. row ***************************
Table: t1
Create Table: CREATE TABLE `t1` (
`c1` int(11) NOT NULL DEFAULT '0',
`c2` varchar(128) DEFAULT NULL,
`c3` varchar(64) DEFAULT NULL,
`c4` int(11) DEFAULT NULL,
PRIMARY KEY (`c1`),
KEY `ind_c2` (`c2`),
KEY `ind_c4` (`c4`),
KEY `ind_c2_c4` (`c2`,`c4`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
ERROR:
No query specified
root@D0DCS 15:17:30 [jing]> select * from t1;
+----+------+------+------+
| c1 | c2 | c3 | c4 |
+----+------+------+------+
| 1 | a | A | 10 |
| 2 | b | B | 20 |
| 3 | b | BB | 20 |
| 4 | b | BBB | 30 |
| 5 | b | BBB | 40 |
| 6 | c | C | 50 |
| 7 | d | D | 60 |
+----+------+------+------+
7 rows in set (0.00 sec)
#打開profiling 的設置
SET profiling = 1;
SHOW VARIABLES LIKE '%profiling%';
#查看隊列的內容
show profiles;
#來查看統計信息
show profile block io,cpu for query 3;
root@D0DCS 14:46:31 [jing]> explain select * from t1 where c2='b' and c4=20;
+----+-------------+-------+------+-------------------------+--------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+-------------------------+--------+---------+-------+------+-------------+
| 1 | SIMPLE | t1 | ref | ind_c2,ind_c4,ind_c2_c4 | ind_c4 | 5 | const | 2 | Using where |
+----+-------------+-------+------+-------------------------+--------+---------+-------+------+-------------+
1 row in set (0.00 sec)
查看查看OPTIMIZER_TRACE方法:
set optimizer_trace="enabled=on";
set optimizer_trace_max_mem_size=1000000;
root@D0DCS 14:47:12 [jing]> set end_markers_in_json=on;
Query OK, 0 rows affected (0.00 sec)
root@D0DCS 14:55:15 [jing]> explain select * from t1 where c2='b' and c4=20;
+----+-------------+-------+------+-------------------------+--------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+-------------------------+--------+---------+-------+------+-------------+
| 1 | SIMPLE | t1 | ref | ind_c2,ind_c4,ind_c2_c4 | ind_c4 | 5 | const | 2 | Using where |
+----+-------------+-------+------+-------------------------+--------+---------+-------+------+-------------+
1 row in set (0.00 sec)
root@D0DCS 14:55:44 [jing]> select * from information_schema.optimizer_trace\G;
*************************** 1. row ***************************
QUERY: explain select * from t1 where c2='b' and c4=20
TRACE: {
"steps": [
{
"join_preparation": { ---優化準備工作
"select#": 1,
"steps": [
{
"expanded_query": "/* select#1 */ select `t1`.`c1` AS `c1`,`t1`.`c2` AS `c2`,`t1`.`c3` AS `c3`,`t1`.`c4` AS `c4` from `t1` where ((`t1`.`c2` = 'b') and (`t1`.`c4` = 20))"
}
] /* steps */
} /* join_preparation */
},
{
"join_optimization": { ---優化工作的主要階段,包括邏輯優化和物理優化兩個階段
"select#": 1,
"steps": [ ---優化工作的主要階段,邏輯優化階段
{
"condition_processing": { ---邏輯優化,條件化簡
"condition": "WHERE",
"original_condition": "((`t1`.`c2` = 'b') and (`t1`.`c4` = 20))",
"steps": [
{
"transformation": "equality_propagation", --邏輯優化,條件化簡,等式處理
"resulting_condition": "((`t1`.`c2` = 'b') and multiple equal(20, `t1`.`c4`))"
},
{
"transformation": "constant_propagation", --邏輯優化,條件化簡,常量處理
"resulting_condition": "((`t1`.`c2` = 'b') and multiple equal(20, `t1`.`c4`))"
},
{
"transformation": "trivial_condition_removal", --邏輯優化,條件化簡,條件去除
"resulting_condition": "((`t1`.`c2` = 'b') and multiple equal(20, `t1`.`c4`))"
}
] /* steps */
} /* condition_processing */
},
{ ---邏輯優化,條件化簡,結束
"table_dependencies": [ ---邏輯優化,找出表之間的相互依賴關係,非直接可用的優化方式
{
"table": "`t1`",
"row_may_be_null": false,
"map_bit": 0,
"depends_on_map_bits": [
] /* depends_on_map_bits */
}
] /* table_dependencies */
},
{
"ref_optimizer_key_uses": [ ---邏輯優化,找出備選的索引
{
"table": "`t1`",
"field": "c2",
"equals": "'b'",
"null_rejecting": false
},
{
"table": "`t1`",
"field": "c4",
"equals": "20",
"null_rejecting": false
},
{
"table": "`t1`",
"field": "c2",
"equals": "'b'",
"null_rejecting": false
},
{
"table": "`t1`",
"field": "c4",
"equals": "20",
"null_rejecting": false
}
] /* ref_optimizer_key_uses */
},
{
"rows_estimation": [ --邏輯優化,估算每個表的元組個數,單表上進行全表掃描和索引掃描的代價估算,每個索引都估算掃描代價
{
"table": "`t1`",
"range_analysis": {
"table_scan": { --邏輯優化, 估算每個表的元組個數. 單表上進行全表掃描的代價
"rows": 7,
"cost": 4.5
} /* table_scan */,
"potential_range_indices": [ ---邏輯優化, 列出備選的索引. 後續版本字符串變爲potential_range_ind
{
"index": "PRIMARY", ---邏輯優化, 本行表明主鍵索引不可用
"usable": false, -- 這個表明這個索引不能用於該語句
"cause": "not_applicable"
},
{
"index": "ind_c2", ---邏輯優化, 索引ind_c2
"usable": true,
"key_parts": [
"c2",
"c1"
] /* key_parts */
},
{
"index": "ind_c4", ---邏輯優化, 索引ind_c4
"usable": true,
"key_parts": [
"c4",
"c1"
] /* key_parts */
},
{
"index": "ind_c2_c4", ---邏輯優化, 索引ind_c2_c4
"usable": true,
"key_parts": [
"c2",
"c4",
"c1"
] /* key_parts */
}
] /* potential_range_indices */,
"setup_range_conditions": [ ---邏輯優化, 如果有可下推的條件,則帶條件考慮範圍查詢
] /* setup_range_conditions */,
"group_index_range": { ---邏輯優化, 如帶有GROUPBY或DISTINCT,則考慮是否有索引可優化這種操作. 並考慮帶有MIN/MAX的情況
"chosen": false,
"cause": "not_group_by_or_distinct"
} /* group_index_range */,
"analyzing_range_alternatives": { ---邏輯優化,開始計算每個索引做範圍掃描的花費(等值比較是範圍掃描的特例)
"range_scan_alternatives": [
{
"index": "ind_c2",
"ranges": [
"b <= c2 <= b"
] /* ranges */,
"index_dives_for_eq_ranges": true,
"rowid_ordered": true,
"using_mrr": false,
"index_only": false,
"rows": 4,
"cost": 5.81,
"chosen": false,
"cause": "cost"
},
{
"index": "ind_c4",
"ranges": [
"20 <= c4 <= 20"
] /* ranges */,
"index_dives_for_eq_ranges": true,
"rowid_ordered": true,
"using_mrr": false,
"index_only": false,
"rows": 2,
"cost": 3.41, ---邏輯優化,這個索引的代價最小
"chosen": true ---邏輯優化,這個索引的代價最小,被選中. (比前面的table_scan 和其他索引的代價都小)
},
{
"index": "ind_c2_c4",
"ranges": [
"b <= c2 <= b AND 20 <= c4 <= 20"
] /* ranges */,
"index_dives_for_eq_ranges": true,
"rowid_ordered": true,
"using_mrr": false,
"index_only": false,
"rows": 2,
"cost": 3.41,
"chosen": false,
"cause": "cost"
}
] /* range_scan_alternatives */,
"analyzing_roworder_intersect": {
"intersecting_indices": [
{
"index": "ind_c2_c4",
"index_scan_cost": 1.0476,
"cumulated_index_scan_cost": 1.0476,
"disk_sweep_cost": 1.75,
"cumulated_total_cost": 2.7976,
"usable": true,
"matching_rows_now": 2,
"isect_covering_with_this_index": false,
"chosen": true
},
{
"index": "ind_c4",
"cumulated_total_cost": 2.7976,
"usable": false,
"cause": "does_not_reduce_cost_of_intersect"
},
{
"index": "ind_c2",
"cumulated_total_cost": 2.7976,
"usable": false,
"cause": "does_not_reduce_cost_of_intersect"
}
] /* intersecting_indices */,
"clustered_pk": {
"clustered_pk_added_to_intersect": false,
"cause": "no_clustered_pk_index"
} /* clustered_pk */,
"chosen": false,
"cause": "too_few_indexes_to_merge"
} /* analyzing_roworder_intersect */
} /* analyzing_range_alternatives */, ---邏輯優化,開始計算每個索引做範圍掃描的花費. 這項工作結算
"chosen_range_access_summary": { ---邏輯優化,開始計算每個索引做範圍掃描的花費. 總結本階段最優的.
"range_access_plan": {
"type": "range_scan",
"index": "ind_c4",
"rows": 2,
"ranges": [
"20 <= c4 <= 20"
] /* ranges */
} /* range_access_plan */,
"rows_for_plan": 2,
"cost_for_plan": 3.41,
"chosen": true -- 這裏看到的cost和rows都比 indx_user 要來的小很多---這個和[A]處是一樣的,是信息彙總.
} /* chosen_range_access_summary */
} /* range_analysis */
}
] /* rows_estimation */ ---邏輯優化, 估算每個表的元組個數. 行估算結束
},
{
"considered_execution_plans": [ ---物理優化, 開始多表連接的物理優化計算
{
"plan_prefix": [
] /* plan_prefix */,
"table": "`t1`",
"best_access_path": {
"considered_access_paths": [
{
"access_type": "ref",
"index": "ind_c2",
"rows": 4,
"cost": 2.8,
"chosen": true
},
{
"access_type": "ref", ---物理優化, 計算indx_user索引上使用ref方查找的花費,
"index": "ind_c4",
"rows": 2,
"cost": 2.4,
"chosen": true
},
{
"access_type": "ref",
"index": "ind_c2_c4",
"rows": 2,
"cost": 2.4,
"chosen": false
},
{
"access_type": "range",
"cause": "heuristic_index_cheaper",
"chosen": false
}
] /* considered_access_paths */
} /* best_access_path */,
"cost_for_plan": 2.4,
"rows_for_plan": 2,
"chosen": true
}
] /* considered_execution_plans */
},
{
"attaching_conditions_to_tables": { --邏輯優化,儘量把條件綁定到對應的表上
"original_condition": "((`t1`.`c4` = 20) and (`t1`.`c2` = 'b'))",
"attached_conditions_computation": [
] /* attached_conditions_computation */,
"attached_conditions_summary": [
{
"table": "`t1`",
"attached": "(`t1`.`c2` = 'b')"
}
] /* attached_conditions_summary */
} /* attaching_conditions_to_tables */
},
{
"refine_plan": [
{
"table": "`t1`" ---邏輯優化,下推索引條件"pushed_index_condition";其他條件附加到表上做爲過濾條件"table_condition_attached"
}
] /* refine_plan */
}
] /* steps */
} /* join_optimization */ ---邏輯優化和物理優化結束
},
{
"join_explain": {
"select#": 1,
"steps": [
] /* steps */
} /* join_explain */
}
] /* steps */
}
MISSING_BYTES_BEYOND_MAX_MEM_SIZE: 0
INSUFFICIENT_PRIVILEGES: 0
1 row in set (0.00 sec)
ERROR:
No query specified
上面是比較各個索引的成本,從輸出上看, ind_c4 的 cost 是 3.41, ind_c2_c4 的cost也是3.41,
"chosen": true 表明優化器選擇了 ind_c4
爲什麼會選擇 ind_c4呢?主要是 ind_c2_c4 的掃描範圍更多,
ranges 是 "b <= c2 <= b AND 20 <= c4 <= 20" ,
而 ind_c4 是 "20 <= c4 <= 20"
mysql的trace跟蹤
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.