MySQL5.6的10053,CBO如何选择执行计划
2017-08-22 15:54
423 查看
mysql> select version();
+------------+
| version() |
+------------+
| 5.6.24-log |
+------------+
1 row in set (0.00 sec)
mysql> create table a (c1 int);
Query OK, 0 rows affected (0.32 sec)
mysql> insert into a values(1);
Query OK, 1 row affected (0.01 sec)
mysql> insert into a values(2);
Query OK, 1 row affected (0.00 sec)
mysql> insert into a values(3);
Query OK, 1 row affected (0.00 sec)
mysql> insert into a values(4);
Query OK, 1 row affected (0.01 sec)
mysql> insert into a values(5);
Query OK, 1 row affected (0.00 sec)
mysql> insert into a values(6);
Query OK, 1 row affected (0.01 sec)
mysql> explain select * from a where c1=6;
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | a | ALL | NULL | NULL | NULL | NULL | 6 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
mysql> create index ind_a_c1 on a(c1);
Query OK, 0 rows affected (0.06 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> explain select * from a where c1=6;
+----+-------------+-------+------+---------------+----------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+----------+---------+-------+------+-------------+
| 1 | SIMPLE | a | ref | ind_a_c1 | ind_a_c1 | 5 | const | 1 | Using index |
+----+-------------+-------+------+---------------+----------+---------+-------+------+-------------+
1 row in set (0.00 sec)
#开启trace
mysql> set optimizer_trace='enabled=on';
Query OK, 0 rows affected (0.00 sec)
#设置trace大小
mysql> set optimizer_trace_max_mem_size=1000000;
Query OK, 0 rows affected (0.00 sec)
#增加trace中注释
mysql> set end_markers_in_json=on;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from a where c1=6;
+------+
| c1 |
+------+
| 6 |
+------+
1 row in set (0.00 sec)
mysql> select * from information_schema.optimizer_trace\G
*************************** 1. row ***************************
QUERY: select * from a where c1=6
TRACE: {
"steps": [
{
"join_preparation": {#优化准备工作
"select#": 1,
"steps": [
{
"expanded_query": "/* select#1 */ select `a`.`c1` AS `c1` from `a` where (`a`.`c1` = 6)"
}
] /* steps */
} /* join_preparation */
},
{
"join_optimization": {#优化的主要阶段,包括逻辑优化和物理优化两个阶段
"select#": 1,
"steps": [
{
"condition_processing": {
"condition": "WHERE",
"original_condition": "(`a`.`c1` = 6)",
"steps": [
{
"transformation": "equality_propagation", #逻辑优化,等式处理
"resulting_condition": "multiple equal(6, `a`.`c1`)"
},
{
"transformation": "constant_propagation",
"resulting_condition": "multiple equal(6, `a`.`c1`)"
},
{
"transformation": "trivial_condition_removal",
"resulting_condition": "multiple equal(6, `a`.`c1`)"
}
] /* steps */
} /* condition_processing */
},
{
"table_dependencies": [#逻辑优化, 找出表之间的相互依赖关系. 非直接可用的优化方式
{
"table": "`a`",
"row_may_be_null": false,
"map_bit": 0,
"depends_on_map_bits": [
] /* depends_on_map_bits */
}
] /* table_dependencies */
},
{
"ref_optimizer_key_uses": [ #逻辑优化,找出备选的索引
{
"table": "`a`",
"field": "c1",
"equals": "6",
"null_rejecting": false
}
] /* ref_optimizer_key_uses */
},
{
"rows_estimation": [#逻辑优化, 估算rows,单表上进行全表扫描和索引扫描的代价估算. 每个索引都估算索引扫描代价
{
"table": "`a`",
"range_analysis": {
"table_scan": {
"rows": 6,
"cost": 4.3
} /* table_scan */,
"potential_range_indices": [#逻辑优化, 列出备选的索引
{
"index": "ind_a_c1",
"usable": true,
"key_parts": [
"c1"
] /* key_parts */
}
] /* potential_range_indices */,
"best_covering_index_scan": {
"index": "ind_a_c1",
"cost": 2.2067,
"chosen": true
} /* best_covering_index_scan */,
"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_a_c1",
"ranges": [
"6 <= c1 <= 6"
] /* ranges */,
"index_dives_for_eq_ranges": true,
"rowid_ordered": true,
"using_mrr": false,
"index_only": true,
"rows": 1,
"cost": 2.21,
"chosen": false,
"cause": "cost"
}
] /* range_scan_alternatives */,
"analyzing_roworder_intersect": {
"usable": false,
"cause": "too_few_roworder_scans"
} /* analyzing_roworder_intersect */
} /* analyzing_range_alternatives */
} /* range_analysis */
}
] /* rows_estimation */
},
{
"considered_execution_plans": [
{
"plan_prefix": [
] /* plan_prefix */,
"table": "`a`",
"best_access_path": {
"considered_access_paths": [ #物理优化计算ind_a_c1索引上使用ref方查找的花费,
{
"access_type": "ref",
"index": "ind_a_c1",
"rows": 1,
"cost": 1.2,
"chosen": true #逻辑优化,这个索引的代价最小,被选中。
},
{
"access_type": "scan",
"cost": 2.2,
"rows": 6,
"cause": "cost",
"chosen": false
}
] /* considered_access_paths */
} /* best_access_path */,
"cost_for_plan": 1.2,
"rows_for_plan": 1,
"chosen": true
}
] /* considered_execution_plans */
},
{
"attaching_conditions_to_tables": {
"original_condition": "(`a`.`c1` = 6)",
"attached_conditions_computation": [
] /* attached_conditions_computation */,
"attached_conditions_summary": [
{
"table": "`a`",
"attached": null
}
] /* attached_conditions_summary */
} /* attaching_conditions_to_tables */
},
{
"refine_plan": [
{
"table": "`a`"
}
] /* refine_plan */
}
] /* steps */
} /* join_optimization */
},
{
"join_execution": {
"select#": 1,
"steps": [
] /* steps */
} /* join_execution */
}
] /* steps */
}
MISSING_BYTES_BEYOND_MAX_MEM_SIZE: 0
INSUFFICIENT_PRIVILEGES: 0
1 row in set (0.01 sec)
+------------+
| version() |
+------------+
| 5.6.24-log |
+------------+
1 row in set (0.00 sec)
mysql> create table a (c1 int);
Query OK, 0 rows affected (0.32 sec)
mysql> insert into a values(1);
Query OK, 1 row affected (0.01 sec)
mysql> insert into a values(2);
Query OK, 1 row affected (0.00 sec)
mysql> insert into a values(3);
Query OK, 1 row affected (0.00 sec)
mysql> insert into a values(4);
Query OK, 1 row affected (0.01 sec)
mysql> insert into a values(5);
Query OK, 1 row affected (0.00 sec)
mysql> insert into a values(6);
Query OK, 1 row affected (0.01 sec)
mysql> explain select * from a where c1=6;
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | a | ALL | NULL | NULL | NULL | NULL | 6 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
mysql> create index ind_a_c1 on a(c1);
Query OK, 0 rows affected (0.06 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> explain select * from a where c1=6;
+----+-------------+-------+------+---------------+----------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+----------+---------+-------+------+-------------+
| 1 | SIMPLE | a | ref | ind_a_c1 | ind_a_c1 | 5 | const | 1 | Using index |
+----+-------------+-------+------+---------------+----------+---------+-------+------+-------------+
1 row in set (0.00 sec)
#开启trace
mysql> set optimizer_trace='enabled=on';
Query OK, 0 rows affected (0.00 sec)
#设置trace大小
mysql> set optimizer_trace_max_mem_size=1000000;
Query OK, 0 rows affected (0.00 sec)
#增加trace中注释
mysql> set end_markers_in_json=on;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from a where c1=6;
+------+
| c1 |
+------+
| 6 |
+------+
1 row in set (0.00 sec)
mysql> select * from information_schema.optimizer_trace\G
*************************** 1. row ***************************
QUERY: select * from a where c1=6
TRACE: {
"steps": [
{
"join_preparation": {#优化准备工作
"select#": 1,
"steps": [
{
"expanded_query": "/* select#1 */ select `a`.`c1` AS `c1` from `a` where (`a`.`c1` = 6)"
}
] /* steps */
} /* join_preparation */
},
{
"join_optimization": {#优化的主要阶段,包括逻辑优化和物理优化两个阶段
"select#": 1,
"steps": [
{
"condition_processing": {
"condition": "WHERE",
"original_condition": "(`a`.`c1` = 6)",
"steps": [
{
"transformation": "equality_propagation", #逻辑优化,等式处理
"resulting_condition": "multiple equal(6, `a`.`c1`)"
},
{
"transformation": "constant_propagation",
"resulting_condition": "multiple equal(6, `a`.`c1`)"
},
{
"transformation": "trivial_condition_removal",
"resulting_condition": "multiple equal(6, `a`.`c1`)"
}
] /* steps */
} /* condition_processing */
},
{
"table_dependencies": [#逻辑优化, 找出表之间的相互依赖关系. 非直接可用的优化方式
{
"table": "`a`",
"row_may_be_null": false,
"map_bit": 0,
"depends_on_map_bits": [
] /* depends_on_map_bits */
}
] /* table_dependencies */
},
{
"ref_optimizer_key_uses": [ #逻辑优化,找出备选的索引
{
"table": "`a`",
"field": "c1",
"equals": "6",
"null_rejecting": false
}
] /* ref_optimizer_key_uses */
},
{
"rows_estimation": [#逻辑优化, 估算rows,单表上进行全表扫描和索引扫描的代价估算. 每个索引都估算索引扫描代价
{
"table": "`a`",
"range_analysis": {
"table_scan": {
"rows": 6,
"cost": 4.3
} /* table_scan */,
"potential_range_indices": [#逻辑优化, 列出备选的索引
{
"index": "ind_a_c1",
"usable": true,
"key_parts": [
"c1"
] /* key_parts */
}
] /* potential_range_indices */,
"best_covering_index_scan": {
"index": "ind_a_c1",
"cost": 2.2067,
"chosen": true
} /* best_covering_index_scan */,
"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_a_c1",
"ranges": [
"6 <= c1 <= 6"
] /* ranges */,
"index_dives_for_eq_ranges": true,
"rowid_ordered": true,
"using_mrr": false,
"index_only": true,
"rows": 1,
"cost": 2.21,
"chosen": false,
"cause": "cost"
}
] /* range_scan_alternatives */,
"analyzing_roworder_intersect": {
"usable": false,
"cause": "too_few_roworder_scans"
} /* analyzing_roworder_intersect */
} /* analyzing_range_alternatives */
} /* range_analysis */
}
] /* rows_estimation */
},
{
"considered_execution_plans": [
{
"plan_prefix": [
] /* plan_prefix */,
"table": "`a`",
"best_access_path": {
"considered_access_paths": [ #物理优化计算ind_a_c1索引上使用ref方查找的花费,
{
"access_type": "ref",
"index": "ind_a_c1",
"rows": 1,
"cost": 1.2,
"chosen": true #逻辑优化,这个索引的代价最小,被选中。
},
{
"access_type": "scan",
"cost": 2.2,
"rows": 6,
"cause": "cost",
"chosen": false
}
] /* considered_access_paths */
} /* best_access_path */,
"cost_for_plan": 1.2,
"rows_for_plan": 1,
"chosen": true
}
] /* considered_execution_plans */
},
{
"attaching_conditions_to_tables": {
"original_condition": "(`a`.`c1` = 6)",
"attached_conditions_computation": [
] /* attached_conditions_computation */,
"attached_conditions_summary": [
{
"table": "`a`",
"attached": null
}
] /* attached_conditions_summary */
} /* attaching_conditions_to_tables */
},
{
"refine_plan": [
{
"table": "`a`"
}
] /* refine_plan */
}
] /* steps */
} /* join_optimization */
},
{
"join_execution": {
"select#": 1,
"steps": [
] /* steps */
} /* join_execution */
}
] /* steps */
}
MISSING_BYTES_BEYOND_MAX_MEM_SIZE: 0
INSUFFICIENT_PRIVILEGES: 0
1 row in set (0.01 sec)
相关文章推荐
- 设置10053跟踪SQL执行计划过程选择事件
- MySql中如何使用 explain 查询 SQL 的执行计划
- 如何通过10053查看SQL语句执行计划
- MySQL中通过EXPLAIN如何分析SQL的执行计划详解
- 通过trace分析优化其如何选择执行计划
- 初步理解MySQL(5.6)的执行计划
- Oracle中利用10053事件来分析Oracle是如何做出最终的执行计划
- 如何根据执行计划,判断Mysql语句是否走索引
- mysql innodb 如何获取用于 生成执行计划的 数据表统计信息
- 初步理解MySQL(5.6)的执行计划
- Oracle CBO 统计信息的收集与执行计划的选择
- Oracle CBO 统计信息的收集与执行计划的选择
- mysql查询优化器为什么可能会选择错误的执行计划
- mysql查缺补漏(二)mysql5.6性能优化(explain执行计划术语,索引,优化查询)
- MySQL 5.5/5.6/5.7及以上版本安装包安装时如何选择安装路径
- mysql中如何查看优化器优化后的执行计划
- 当统计信息不准确时,CBO可能产生错误的执行计划,并在10053 trace中找到CBO出错的位置示例
- MySql学习(七) —— 查询性能优化 深入理解MySql如何执行查询
- MySql学习(七) —— 查询性能优化 深入理解MySql如何执行查询