数据库索引意在提升检索效率。
通过创建唯一索引可以保证数据库表中每一行数据的唯一性。排序后可以将随机的I/O转换成顺序I/O。
索引是如何提高检索速度的?
将无序的数据存储转为相对有序的数据。
索引为什么不是越多越好?
- 对表中的数据进行insert/update/delete时,索引需要动态维护,占用时间。
- 索引建立后需要占用存储空间,如果是聚簇索引,占用的存储空间更大。
MySQL数据库主要使用的两种数据结构
-
哈希索引
(图片来源于网络,侵删)
哈希索引检索速度很快,但是也存在一定的局限性:
1)哈希索引没有办法利用索引完成排序
2)有重复键值的情况下,会发生哈希碰撞,索引效率较低
3)不支持范围查询
4)不支持最左匹配原则 -
B+Tree索引
(图片来源于网络,侵删)
每一页存在一个record_type:
0:普通的用户记录
1:目录项记录
2:最小记录
3:最大记录
目录项记录只有主键值和页的编号两个列,而普通的用户记录的列是用户自己定义的(Innodb为列,MyISAM的叶子节点存储记录的指针),可能包含很多列,另外还有InnoDB自己添加的隐藏列。
Innodb和MySIAM实现B+Tree的方式:聚簇索引 & 非聚簇索引
(图片来源于网络,侵删)
聚簇索引:
叶子节点存储了完整的用户记录
在Innodb中,会自动创建聚簇索引,聚簇索引就是数据的存储方式。一张表有且仅有一个聚簇索引。
1)如果表定义了PK,则PK就是聚簇索引
2)如果表没有定义PK,则第一个not NULL unique列就是聚簇索引
3)否则,Innodb会创建一个隐藏的row-id作为聚簇索引
普通索引(二级索引,辅助索引,非聚簇索引)
对于Innodb来说二级索引的叶子节点存放的是索引列的值与主键
MyISAM因为存放的全是主键和行号,意味着MyISAM中建立的索引全部都是二级索引,那么MyISAM均需要回表查询。
索引覆盖
explain查询计划优化,即explain的输出结果Extra字段为Using index时,能够触发索引覆盖。
只需要在一棵索引树上就能获取SQL所需的所有列数据,无需回表,速度更快。
常见的方法是:将被查询的字段,建立到联合索引里去。
哪些情况可以利用索引覆盖来优化SQL:
1)全表count查询优化
2)列查询回表优化
3)分页查询
复合索引的范围查询与最左原则:
- SQL语句中where子句中范围查询之后的列无法使用联合索引
- 在mysql建立联合索引时会遵循最左前缀匹配的原则,即最左优先,在检索数据时从联合索引的最左边开始匹配