mysql的trace跟踪


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)