EXPLAIN
1. explain+sql:分析执行索引、扫描行数及优化空间等
2. show warnings:显示最后一个执行的语句所产生的错误、警告和提示等信息
存储引擎对比
特性
InnoDB
MyISAM
存储限制
64TB
256TB
事务
支持
不支持
锁粒度
行级锁
表级锁
外键
支持
不支持
支持的索引
B-Tree、全文索引(5.6开始支持,但不支持中文;5.7开始支持中文)、哈希索引(引擎自适应,不支持自定义)
B-Tree、全文索引
表行数统计
通过全表扫描,动态统计
已存储表行数
索引
选择关键字越小的那些列建索引,增加关键字的个数,增大m,减少树的高度
索引特性对比表
特性
B+TREE
HASH 索引
等值查询
支持
支持
范围查询
支持
不支持
使用部分索引键查询
支持
不支持
结果排序
支持
不支持
查询平均时间复杂度
O(logm)
m为单节点关键字个数,n为总关键字个数,m越大,树高越低,查询复杂度越小
O(1)
等值查询高效,但键重复率高时性能退化
聚簇索引和非聚簇索引
聚簇索引(主键索引)
-
提升IO密集型应用性能(顺序读取)
-
Row的移动不影响二级索引
-
如果主键值非自增(随机生成但有序),在插入记录时,可能造成记录移动或页分裂,影响性能
非聚簇索引
-
索引与数据分离,相对聚簇索引来说,占用空间小
-
InnoDB二级索引,相对MyISAM会更大
-
使用InnoDB二级索引,select *涉及回表,需要检索两次B+Tree
-
Row的移动,会影响MyISAM索引,没事不要移动数据
-
随机IO(SSD硬盘比较普遍,所以可忽略这部分影响)
索引设计理念
哪些列建议需要用到索引
WHERE、JOIN、GROUP BY、ORDER BY等语句用到的列
利用最左前缀
(A,B,C),按A排序,A相同再按B排序,以此类推
如何选择索引列的顺序
-
经常使用到的列优先
- 利用最左前缀,尽量复用已用索引
-
区分度大的列优先(对性别建索引,不如对姓名建索引)
-
区分度=列的所有不重复的值/所有值的个数,至少大于0.1(不大于0.1不建议建索引)
-
尽快排除掉更多的记录
-
-
宽度小的列优先(数据的大小,列的值越小,索引树的一个节点能存的key越多)
-
列宽度=列的数据类型
-
宽度越小,单节点的key值越多,索引树的高度越低,查询复杂度越低,性能越好
-
索引使用建议
type:连接的类型
-
const、system:最多一个匹配行,使用主键或者unique索引(where id=xx)
-
eq_ref:返回一行数据,通常在联接时出现,使用主键或者unique索引(联接的时候,右表采用的类型)
-
ref:使用key的最左前缀,且key不是主键或unique键(线上最常见)
-
range:索引范围扫描,对索引的扫描开始于某一点,返回匹配的行(线上保底)
-
index:以索引的顺序进行全表扫描,优点是不用排序,缺点是还需要全表扫描
-
all:全表扫描,必须避免
从上到下,是从建议到不建议的类型
range及以上是建议的类型,尽量避免index,杜绝使用all
extra:
using index:索引覆盖,查询只用到索引即可,无需回表,读取数据快
using where:在存储引擎返回记录后,再做过滤
using temporary:使用临时表,通常在GROUP BY、ORDER BY时出现(尽量不要出现,浪费存储的空间)
using filesort:用到非索引顺序的额外排序,额外的排序(可能是内存的排序,也可能是外排,即执行引擎层面去做的排序),取决于sortBuffer的大小
一旦使用了外排,性能就会出现比较大的退化——当ORDER BY未用到索引时会发生(一定要规避)
EXPLAIN的分析
- key是不能为NULL的,如果为NULL说明本次没有可用的索引,进行了全表的扫描
2. rows越小越好,虽然是估算
3. key_len,可理解为,使用了索引的哪些字段,长度加到一起
长度不需要具体去记,allow null使用时一定要慎重
不损失精确性的话,key_len越小越好;用不到的字段,移除
Force Index的用法
select * from xx force index xx where xx order by xx
问题记录
-
using temporary:
-
暂存结果集,如果内存够用,就在内存,如果内存不够用,建一个临时表,外排
另一个表关联,a和b关联,再和c关联,a和b关联的结果会创建一个临时表
-
在关联、排序结果的临时表
-
-
using index condition:
- 查询结果的下推,联合索引(a、b、c),where a = xx and c = xx