5. MySQL执行计划
explain select * from lineitem where l_orderkey=3 and l_shipdate='1994-01-16';
id select_type table type possible_keys key key_len ref rows Extra
PRIMARY, Using
1 SIMPLE lineitem ref PRIMARY 4 const 8
li_shp_dt_idx where
▪ 执行计划
▫ MySQL通过查询优化器对Query涉及的表的相关统计信息进行分析,得到一个认
为最合理最优化的数据数据访问方式,也就是常说的“执行计划”。
▫ 通过执行计划可以知道什么时候必须为表建立索引以得到一个使用索引来查询记录
的更快的select,优化器是否以一个最佳次序连接表。
6. MySQL执行计划
explain select * from lineitem where l_orderkey=3 and l_shipdate='1994-01-16';
id select_type table type possible_keys key key_len ref rows Extra
PRIMARY, Using
1 SIMPLE lineitem ref PRIMARY 4 const 8
li_shp_dt_idx where
▪ 执行计划的语法
▪ EXPLAIN tbl_name; ---- DESCRIBE tbl_name;
▪ EXPLAIN [EXTENDED] SELECT select_options;
7. MySQL执行计划解析
id select_type table type possible_keys key key_len ref rows Extra
PRIMARY, Using
1 SIMPLE lineitem ref PRIMARY 4 const 8
li_shp_dt_idx where
▫ id
SELECT标识符
▫ table
输出行所引用的表名
▫ possible_keys
MySQL执行查询时可以使用的索引
▫ key IMPORTANT
MySQL优化器选择使用的索引,如果没有选择索引,值为NULL
8. MySQL执行计划解析
id select_type table type possible_keys key key_len ref rows Extra
PRIMARY, Using
1 SIMPLE lineitem ref PRIMARY 4 const 8
li_shp_dt_idx where
▫ key_len
MySQL决定使用的索引键长度
▫ ref
列出是使用某个表的某个字段( join )or常量const来与key一起进行过滤
▫ rows IMPORTANT
MySQL查询优化器通过系统收集的统计信息估算的结果集记录行数
9. MySQL执行计划解析
id select_type table type possible_keys key key_len ref rows Extra
PRIMARY, Using
1 SIMPLE lineitem ref PRIMARY 4 const 8
li_shp_dt_idx where
▫ select_type
▫ SIMPLE 简单的SELECT,即不使用表连接或子查询
▫ PRIMARY 主查询,子查询中最外层的查询,但并非一定是主键查询
▫ UNION UNION诧句中的第二个SELECT或之后的SELECT诧句
▫ DEPENDENT UNION 子查询UNION中第二个SELECT或之后的SELECT诧句,且依赖于外部查询结果集
▫ UNION RESULT UNION的结果
10. MySQL执行计划解析
id select_type table type possible_keys key key_len ref rows Extra
PRIMARY, Using
1 SIMPLE lineitem ref PRIMARY 4 const 8
li_shp_dt_idx where
▫ SUBQUERY 子查询中的第一个SELECT,结果不依赖于外部查询结果集
▫ DEPENDENT SUBQUERY 子查询中的第一个SELECT,依赖于外部查询结果集
▫ DERIVED 用于导出表的SELECT诧句(FROM子句中的子查询)
▫ UNCACHEABLE SUBQUERY UNION中第二个或之后的SELECT,不可被缓冲的子查询
11. Examples select *
key_
id select_type table type possible_keys key ref rows Extra
len
Using
1 PRIMARY customer ALL NULL NULL NULL NULL 150000
where
DEPENDENT
2 orders const PRIMARY,orders_fk1 PK 4 const 1
SUBQUERY
DEPENDENT Using
3 orders range PRIMARY,orders_fk1 PK 4 NULL 2
UNION where
NU UNION
LL
<union2,3> ALL NULL NULL NULL NULL NULL
RESULT
id=2
explain select * from customer where c_custkey IN(select o_custkey from orders where
o_orderkey=1 UNION ALL select o_custkey from orders where o_orderkey IN (10,20) );
id=3
12. MySQL执行计划解析
id select_type table type possible_keys key key_len ref rows Extra
PRIMARY, Using
1 SIMPLE lineitem ref PRIMARY 4 const 8
li_shp_dt_idx where
▫ type IMPORTANT
▫ system
查询的表只有一行数据(系统表),const连接类型的一个特例
▫ const
至多只有一行匹配,在查询开始时被读取
const用于PRIMARY KEY(all)或UNIQUE索引和常数作比较
SELECT * FROM tbl_name WHERE primary_key=1;
SELECT * FROM tbl_name WHERE primary_key_part1=1 AND primary_key_part2=2;
SELECT * FROM tbl_name WHERE unique_key=1;
13. Examples
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 1
2 DERIVED lineitem const PRIMARY PRIMARY 8 1
explain select * from (select * from lineitem where l_orderkey=3 and l_linenumber=2) test;
<derived2>表示查询结果来自一个衍生表,其中2代表该
查询衍生自第二个select查询,即id为2的select。
PRIMARY KEY
TIPS:
INDEX:普通索引
UNIQUE INDEX:唯一性索引,对于每个索引键,表中只有一条记录与之匹配
PRIMARY KEY:主键索引,隐含UNIQUE,NOT NULL
14. MySQL执行计划解析
▫ eq_ref
对于前表的行组合,仅从该表中读取一行。它用在一个索引的所有部分都被连接所使用,并且索引
是UNIQUE NOT NULL或PRIMARY KEY。--唯一性索引扫描
SELECT * FROM ref_table,other_table WHERE ref_table.key_column=other_table.column;
SELECT * FROM ref_table,other_table WHERE ref_table.key_column_part1=other_table.column
AND ref_table.key_column_part2=1;
▫ ref
对于前表的行组合,所有有配索引值的行将从该表中读取。如果连接不能基于关键字选择单个行,
则使用ref。--非唯一性索引扫描
SELECT * FROM ref_table WHERE key_column=expr;
SELECT * FROM ref_table,other_table WHERE ref_table.key_column=other_table.column;
SELECT * FROM ref_table,other_table WHERE ref_table.key_column_part1=other_table.column;
15. Examples
Ext
id select_type table type possible_keys key key_len ref rows
ra
1 SIMPLE orders ALL orders_fk1 NULL NULL NULL 1500000
tpch.orders.
1 SIMPLE customer eq_ref PRIMARY PRIMARY 4 1
o_custkey
explain select * from customer,orders where customer.c_custkey=orders.o_custkey;
PRIMARY KEY
内层循环优化,被驱动表的join字段被索引
TIPS:MySQL中的JOIN算法都是用Nested Loop Join,即通过驱动表的结果集作为循环基础数
据,然后将该结果集中的数据作为过滤条件一条条地到下一个表中查询数据,最后合并结果。
16. Examples
Ext
id select_type table type possible_keys key key_len ref rows
ra
1 SIMPLE orders ALL PRIMARY NULL NULL NULL 1500000
tpch.orders.
1 SIMPLE lineitem ref PRIMARY PRIMARY 4 4
o_orderkey
explain select * from orders,lineitem where lineitem.l_orderkey=orders.o_orderkey;
Ext
id select_type table type possible_keys key key_len ref rows
ra
1 SIMPLE orders ALL PRIMARY NULL NULL NULL 1500000
tpch.orders.
1 SIMPLE lineitem eq_ref PRIMARY PRIMARY 8 o_orderkey, 1
const
explain select * from orders,lineitem where lineitem.l_orderkey=orders.o_orderkey
and l_linenumber=2;
PRIMARY KEY_1
PRIMARY KEY_2
17. MySQL执行计划解析
▫ fulltext
进行全文索引扫描,仅MyISAM,仅CHAR、VARCHAR和TEXT三种数据类型可以建立。
▫ ref_or_null
类似ref,添加了NULL值的查询。在解决子查询中经常使用该连接类型的优化。
SELECT * FROM ref_table WHERE key_column=expr OR key_column IS NULL;
▫ index_merge
索引合并优化,使用两个或多个索引,然后对索引结果进行合并,再读取表数据。
18. Examples
id select_type table type possible_keys key key_len ref rows Extra
Using
index_ li_shp_dt_idx, li_shp_dt_idx, intersect(li_shp_dt_
1 SIMPLE lineitem 3,3 NULL 1
merge li_com_dt_idx li_com_dt_idx idx,li_com_dt_idx);
Usingwhere
explain select * from lineitem where l_commitdate='1996-02-12' and
l_shipdate='1996_02_12';
19. MySQL执行计划解析
▫ unique_subquery
子查询中的返回结果字段组合是主键或唯一约束
value IN (SELECT primary_key FROM single_table WHERE some_expr)
▫ index_subquery
子查询中的返回结果字段组合是一个索引,为非唯一索引
value IN (SELECT key_column FROM single_table WHERE some_expr)
▫ range
索引范围扫描
SELECT * FROM tbl_name WHERE key_column = 10;
SELECT * FROM tbl_name WHERE key_column BETWEEN 10 and 20;
SELECT * FROM tbl_name WHERE key_column IN (10,20,30);
SELECT * FROM tbl_name WHERE key_part1= 10 AND key_part2 IN (10,20,30);
20. MySQL执行计划解析
ATTENTION
▫ index-- Full Index Scan
全索引扫描,比ALL快,因为索引文件通常比数据文件小。当查询的列属于某个索引的一部分时,
使用该种索引。
▫ ALL-- Full Table Scan
全表扫描,特别注意。
21. Examples
id select_type table type possible_keys key key_len ref rows Extra
Using
1 SIMPLE lineitem index NULL PRIMARY 8 NULL 6001215
index
explain select l_orderkey from lineitem;
id select_type table type possible_keys key key_len ref rows Extra
Using
1 SIMPLE lineitem ALL NULL NULL NULL NULL 6001215
where
explain select * from lineitem where l_linestatus='F';
22. MySQL执行计划解析
id select_type table type possible_keys key key_len ref rows Extra
PRIMARY, Using
1 SIMPLE lineitem ref PRIMARY 4 const 8
li_shp_dt_idx where
IMPORTANT
▫ Extra
MySQL解决查询的额外详细信息。注意using filesort和using temporary。
▫ Using filesort
当Query中包含ORDER BY操作,且无法利用索引完成排序操作的时候,MySQL查询
优化器不得不选择相应的排序算法来实现。MySQL需要额外的一次传递,以找出如何
按排序顺序检索行。通过根据连接类型浏览所有行并为所有匹配WHERE子句的行保存
排序关键字和行的指针来完成排序。然后关键字被排序,并按排序顺序检索行
▫ Using temporary
为了解决某些查询,MySQL需要创建一个临时表来存放结果
典型情冴如查询包含可以按不同情冴列出的GROUP BY和ORDER BY子句
23. MySQL执行计划解析
▫ Using where
如果不读取表的所有数据,或不是仅仅通过索引就可以获取所有需要的数据,则出现该信息。
▫ Using index
只访问索引,不读取表获取数据。覆盖索引。
▫ Using join buffer
当join类型为ALL、index、range或index_merge时使用。
▫ Distinct
查找distinct值,当MySQL找到第1个匹配行后,停止为当前的行组合搜索更多的行。
24. MySQL执行计划解析
▫ Impossible WHERE noticed after reading const tables
MySQL 已经读了const(或system)表,并发现WHERE子句false。
▫ No tables used
查询没有FROM子句,或有双重FROM子句。
▫ Using index for group-by
MySQL查询优化器使用松散索引扫描实现GROUP BY或DISTINCT,即完全利用索引扫描
来实现GROUP BY,不需要扫描所有满足条件的索引键即可完成操作。
▫ Full scan on NULL key
子查询优化时,优化器无法使用索引查找时的后备方案。
▫ Range checked for each record (index map:N)
MySQL没有发现好的可以使用的索引,但发现如果来自前面的表的列值已知,可能部分索
引可以使用。对前面的表的每个行组合,MySQL检查是否可以使用range或index_merge访
问方法来索取行。
▫ ……
25. Examples
key_
id select_type table type possible_keys key ref rows Extra
len
Using
where ;
Using
1 PRIMARY orders ALL orders_dt_idx NULL NULL NULL 1498108
temporary;
Using
filesort
Using
DEPENDENT
2 lineitem ref PRIMARY PK 4 tpch.orders. 4 where
SUBQUERY
o_orderkey
explain select * from orders where o_orderdate >= date ' 1993-07-01 '
and exists( select *
from lineitem
where l_orderkey = o_orderkey
and l_commitdate < l_receiptdate )
group by o_orderpriority
order by o_orderpriority;
26. Examples
key_
id select_type table type possible_keys key ref rows Extra
len
Using index
1 SIMPLE lineitem range NULL li_shp_dt_idx 3 NULL 2526
for group-by
explain select distinct l_shipdate from lineitem;