-- 查询 员工
SELECT * FROM `employees` WHERE NAME="LiLei"
-- 查看sql是否使用索引,前面加上 EXPLAIN 即可
EXPLAIN SELECT * FROM `employees` WHERE NAME="LiLei"
expain中的列
expain出来的信息有10列,分别是id、select_type、table、partitions、type、possible_keys、key、key_len、ref、rows、Extra
1:id
- id列的编号是 select 的序列号,有几个 select 就有几个id.
- id的顺序是按 select 出现的顺序增长的。 id列越大执行优先级越高.
- id相同则从上往下执行,id为NULL最后执行。
2:select_type
- simple:简单查询。查询不包含子查询和union
- primary:复杂查询中最外层的 select
- subquery:包含在 select 中的子查询(不在 from 子句中)
- derived:包含在 from 子句中的子查询。MySQL会将结果存放在一个临时表中,也称为派生表
- union:在 union 中的第二个和随后的 select
3:table
- 这一列表示 explain 的一行正在访问哪个表。
4:type
- 表示sql执行类型
- 依次从最优到最差分别为:system > const > eq_ref > ref > range > index > ALL
- 一般来说,得保证查询达到range级别,最好达到ref
5:possible_keys
- 这一列显示,可能使用那些索引来查找
6:key
- 这一列显示,采用哪个索引来查找
7:key_len
- 这一列显示。使用索引的字节
key_len计算规则如下:
字符串,char(n)和varchar(n),5.0.3以后版本中,
n均代表字符数,而不是字节数,
如果是utf-8,一个数字 或字母占1个字节,一个汉字占3个字节
- char(n):如果存汉字长度就是 3n 字节
- varchar(n):如果存汉字则长度是 3n + 2 字节,加的2字节用来存储字符串长度,因为 varchar是变长字符串
数值类型
- tinyint:1字节
- smallint:2字节
- int:4字节
- bigint:8字节
时间类型
- date:3字节timestamp:4字节
- datetime:8字节
如果字段允许为 NULL,需要1字节记录是否为 NULL ,索引最大长度是768字节,当字符串过长时,mysql会做一个类似左前缀索引的处理,将前半部分的字符提取出来做索 引。
8:ref
9:rows
- 这一列是mysql估计要读取并检测的行数(不是结果集里的行数)
10:Extra
- Using index: 使用覆盖索引
- Using where: 使用where来查询结果,并且查询的列没有被索引覆盖
- using index condition:搜索条件中虽然出现了索引列,但是有部分条件无法使用索引,会根据能用索引的条件先搜索一遍再匹配无法使用索引的条件。
- using temporary:创建临时表来处理查询,此时就需要优化
- Using filesort:将用外部排序而不是索引排序
优化避免
- 最左前缀,创建的联合索引,查询从最左前列开始,并且不跳过索引中的列
- 联合索引,如果第一个字段是范围查询,不会走索引
- 查询条件,不能再索引列上做任何操作(计算,函数,类型转换等),会导致索引失效
- 尽量使用覆盖索引(只查询是索引的列),减少select * 语句
- 关联表查询,尽量先查询数据少的表
- is null, is not null 一般无法用索引
- like, 通配符在左边的,索引会失效 '%abc', 通配符在右边 会走索引abc% (如果非使用like,最好使用覆盖索引)
- 字符串不加单引号,索引会失败
- 少用or 或者 in, 在数据少时不会用索引,数据多时会用索引(mysql内部优化器会判断,是否采用索引)
race
mysql最终是否选择走索引或者一张表涉及多个索引,mysql最终如何选择索引,我们可以用trace工具
来一查究竟,开启trace工具会影响mysql性能,所以只能临时分析sql使用,用 完之后立即关闭
trace工具用法:
一:开启trace
SET OPTIMIZER_TRACE="enabled=on",END_MARKERS_IN_JSON=ON;
SET optimizer_trace_offset=-30, optimizer_trace_limit=30;
二:查看是否开启
SHOW VARIABLES LIKE 'optimizer_trace';
三:执行sql
SELECT * FROM employees WHERE NAME = 'LiLei';
四:查询trace
SELECT * FROM information_schema.OPTIMIZER_TRACE
结果:
{
"steps": [
{
"join_preparation": {
"select#": 1,
"steps": [
{
"expanded_query": "/* select#1 */ select `employees`.`id` AS `id`,`employees`.`name` AS `name`,`employees`.`age` AS `age`,`employees`.`position` AS `position`,`employees`.`hire_time` AS `hire_time` from `employees` where (`employees`.`name` = 'LiLei') limit 0,1000"
}
] /* steps */
} /* join_preparation */
},
{
"join_optimization": {
"select#": 1,
"steps": [
{
"condition_processing": {
"condition": "WHERE",
"original_condition": "(`employees`.`name` = 'LiLei')",
"steps": [
{
"transformation": "equality_propagation",
"resulting_condition": "(`employees`.`name` = 'LiLei')"
},
{
"transformation": "constant_propagation",
"resulting_condition": "(`employees`.`name` = 'LiLei')"
},
{
"transformation": "trivial_condition_removal",
"resulting_condition": "(`employees`.`name` = 'LiLei')"
}
] /* steps */
} /* condition_processing */
},
{
"substitute_generated_columns": {
} /* substitute_generated_columns */
},
{
"table_dependencies": [
{
"table": "`employees`",
"row_may_be_null": false,
"map_bit": 0,
"depends_on_map_bits": [
] /* depends_on_map_bits */
}
] /* table_dependencies */
},
{
"ref_optimizer_key_uses": [
{
"table": "`employees`",
"field": "name",
"equals": "'LiLei'",
"null_rejecting": false
},
{
"table": "`employees`",
"field": "name",
"equals": "'LiLei'",
"null_rejecting": false
}
] /* ref_optimizer_key_uses */
},
{
"rows_estimation": [
{
"table": "`employees`",
"range_analysis": {
"table_scan": {
"rows": 199764,
"cost": 239719
} /* table_scan */,
"potential_range_indexes": [
{
"index": "PRIMARY",
"usable": false,
"cause": "not_applicable"
},
{
"index": "idx_name_age_position",
"usable": true,
"key_parts": [
"name",
"age",
"position",
"id"
] /* key_parts */
},
{
"index": "name",
"usable": true,
"key_parts": [
"name",
"id"
] /* key_parts */
}
] /* potential_range_indexes */,
"setup_range_conditions": [
] /* setup_range_conditions */,
"group_index_range": {
"chosen": false,
"cause": "not_group_by_or_distinct"
} /* group_index_range */,
"analyzing_range_alternatives": {
"range_scan_alternatives": [
{
"index": "idx_name_age_position",
"ranges": [
"LiLei <= name <= LiLei"
] /* ranges */,
"index_dives_for_eq_ranges": true,
"rowid_ordered": false,
"using_mrr": false,
"index_only": false,
"rows": 2,
"cost": 3.41,
"chosen": true
},
{
"index": "name",
"ranges": [
"LiLei <= name <= LiLei"
] /* 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": {
"usable": false,
"cause": "too_few_roworder_scans"
} /* analyzing_roworder_intersect */
} /* analyzing_range_alternatives */,
"chosen_range_access_summary": {
"range_access_plan": {
"type": "range_scan",
"index": "idx_name_age_position",
"rows": 2,
"ranges": [
"LiLei <= name <= LiLei"
] /* ranges */
} /* range_access_plan */,
"rows_for_plan": 2,
"cost_for_plan": 3.41,
"chosen": true
} /* chosen_range_access_summary */
} /* range_analysis */
}
] /* rows_estimation */
},
{
"considered_execution_plans": [
{
"plan_prefix": [
] /* plan_prefix */,
"table": "`employees`",
"best_access_path": {
"considered_access_paths": [
{
"access_type": "ref",
"index": "idx_name_age_position",
"rows": 2,
"cost": 2.4,
"chosen": true
},
{
"access_type": "ref",
"index": "name",
"rows": 2,
"cost": 2.4,
"chosen": false
},
{
"access_type": "range",
"range_details": {
"used_index": "idx_name_age_position"
} /* range_details */,
"chosen": false,
"cause": "heuristic_index_cheaper"
}
] /* considered_access_paths */
} /* best_access_path */,
"condition_filtering_pct": 100,
"rows_for_plan": 2,
"cost_for_plan": 2.4,
"chosen": true
}
] /* considered_execution_plans */
},
{
"attaching_conditions_to_tables": {
"original_condition": "(`employees`.`name` = 'LiLei')",
"attached_conditions_computation": [
] /* attached_conditions_computation */,
"attached_conditions_summary": [
{
"table": "`employees`",
"attached": null
}
] /* attached_conditions_summary */
} /* attaching_conditions_to_tables */
},
{
"refine_plan": [
{
"table": "`employees`"
}
] /* refine_plan */
}
] /* steps */
} /* join_optimization */
},
{
"join_execution": {
"select#": 1,
"steps": [
] /* steps */
} /* join_execution */
}
] /* steps */
}