在慢查询优化的过程中 理解explain很重要的一环
已下面这条sql为例
explain select count(*) from clients;
id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
---|---|---|---|---|---|---|---|---|---|
1 | SIMPLE | clients | Index | Null | index_xxx | 1 | Null | 29971 | Using Index |
每种信息的含义
- id: SELECT 查询的标识符. 每个 SELECT 都会自动分配一个唯一的标识符.
- select_type: SELECT 查询的类型.
- table: 查询的是哪个表
- type: 访问类型
- possible_keys: 此次查询中可能选用的索引
- key: 此次查询中确切使用到的索引.
- ref: 哪个字段或常数与 key 一起被使用
- rows: 显示此查询一共扫描了多少行. 这个是一个估计值.
- extra: 额外的信息
type可能会有以下几种类型(效率从高到低)
- system(高效)
这是const连接类型的一种特例,表仅有一行满足条件。 - const(高效)
当确定最多只会有一行匹配的时候,MySQL优化器会在查询前读取它而且只读取一次,因此非常快。
当主键放入where子句时,mysql把这个查询转为一个常量explain select * from orders where id = x;
- eq_ref(高效)
最多只返回一条符合条件的记录。使用唯一性索引或主键查找时会发生explain select * from orders where uniq_key_col = x;
- ref
一种索引访问,它返回所有匹配某个单个值的行。此类索引访问只有当使用非唯一性索引或唯一性索引非唯一性前缀时才会发生。这个类型跟eq_ref不同的是,它用在关联操作只使用了索引的最左前缀,或者索引不是UNIQUE和PRIMARY KEY。ref可以用于使用=或<=>操作符的带索引的列。explain select * from orders where common_key_col = x;
- range
范围扫描,一个有限制的索引扫描。key 列显示使用了哪个索引。当使用=、 <>、>、>=、<、<=、IS NULL、<=>、BETWEEN 或者 IN 操作符,用常量比较关键字列时,可以使用 rangeexplain select * from orders where id in (1,2);
- index
和全表扫描一样。只是扫描表的时候按照索引次序进行而不是行。主要优点就是避免了排序, 但是开销仍然非常大。如在Extra列看到Using index,说明正在使用覆盖索引,只扫描索引的数据,它比按索引次序全表扫描的开销要小很多explain select id from clients;
- Null
意味说mysql能在优化阶段分解查询语句,在执行阶段甚至用不到访问表或索引(高效)
Q: 为什么select count(*) from clients;
这个查询没有选择primary key
A: 通过 explain
我们会发现, 这条语句是一个索引扫描,至于具体选择了那条索引,主要看那个索引的体积更小
explain select count(*) from clients;
primary key 是 clustered index 体积比较大, 肯定扫描更小的索引效率是最高的
通过
show index from clients;
select count(*)
是一个没有办法在优化的查询
如果需要频繁的操作 count cache
或许是一个更好的选择