一、为什么要有索引?
一般的应用系统,读操作的比例远远大于写操作的比例,而且插入操作和一般的更新操作很少出现性能问题。在生产环境中,我们遇到最多的,也是最容易出现性能问题的,还是一些复杂的查询操作,因此对查询语句的优化显然是重中之重。说起查询优化,就不得不提到索引了。
二、什么是索引?
索引在MySQL中也叫是一种“键”,是存储引擎用于快速找到记录的一种数据结构。索引对于良好的性能非常关键,尤其是当表中的数据量越来越大时,索引对于性能的影响愈发重要。
索引,类似书籍的目录,可以根据目录的某个页码立即找到对应的内容。
- 索引的优点:1. 天生排序;2. 快速查找。
- 索引的缺点:1. 占用空间;2. 降低更新表的速度。
注意: 小表使用全表扫描更快,中大表才使用索引。超级大表索引基本无效。
三、索引的原理
索引的目的在于提高查询效率,与我们查阅图书所用的目录是一个道理:先定位到章,然后定位到该章下的一个小节,然后找到页数。相似的例子还有:查字典,查火车车次,飞机航班等。
本质都是:通过不断地缩小想要获取数据的范围来筛选出最终想要的结果,同时把随机的事件变成顺序的事件,也就是说,有了这种索引机制,我们可以总是用同一种查找方式来锁定数据。
数据库也是一样,但显然要复杂的多,因为不仅面临着等值查询,还有范围查询(>、<、between、in)、模糊查询(like)、并集查询(or)等等。数据库应该选择怎么样的方式来应对所有的问题呢?
我们回想字典的例子,能不能把数据分成段,然后分段查询呢?最简单的如果1000条数据,1到100分成第一段,101到200分成第二段,201到300分成第三段…这样查第250条数据,只要找第三段就可以了,一下子去除了90%的无效数据。具体的实现则比较复杂。
MySQL 将数据按照页来存储,默认一页为 16kb,当你在查询时,不会只加载某一条数据,而是将这个数据所在的页都加载到 pageCache 中,这个其实和操作系统( OS) 的就近访问原理类似。
三、索引的分类
1、从实现上分类
索引从实现上分成 2 种:聚簇索引和非聚簇索引(也叫二级索引或者辅助索引)。
MYSQL的索引类型跟存储引擎是相关的,InnoDB存储引擎数据文件跟索引文件全部放在ibd文件中,而MyISAM的数据文件放在myd文件中,索引放在myi文件中,其实区分聚簇索引和非聚簇索引非常简单,只要判断数据跟索引是否存储在一起就可以了。
InnoDB存储引擎在进行数据插入的时候,数据必须要跟索引放在一起,如果有主键就使用主键,没有主键就使用唯一键,没有唯一键就使用6字节的rowid,因此跟数据绑定在一起的就是聚簇索引,而为了避免数据冗余存储,其他的索引的叶子节点中存储的都是聚簇索引的key值,因此InnoDB中既有聚簇索引也有非聚簇索引,而MyISAM中只有非聚簇索引。
2、从功能上分类
索引从从功能上分为 6 种:普通索引、唯一索引、主键索引、复合索引、外键索引、全文索引。
(1)普通索引:最基本的索引,没有任何约束。
(2)唯一索引:与普通索引类似,但具有唯一性约束。
(3)主键索引:特殊的唯一索引,不允许有空值。
(4)复合索引:将多个列组合在一起创建索引,可以覆盖多个列。
(5)外键索引:只有InnoDB类型的表才可以使用外键索引,保证数据的一致性、完整性和实现级联操作。
(6)全文索引:MySQL 自带的全文索引只能用于 InnoDB、MyISAM ,并且只能对英文进行全文检索,一般使用全文索引引擎(ES,Solr)。
四、索引的数据结构
索引的数据结构和具体存储引擎的实现有关,MySQL中使用较多的索引有Hash索引,B+树索引。InnoDB和MyISAM存储引擎的索引实现为B+树,Memory存储引擎为hash索引。
1、B+树索引
B+树是一个平衡的多叉树,从根节点到每个叶子节点的高度差值不超过1,而且同层级的二节点间有指针相关连接,在B+树上的常规检索,从根节点到叶子节点的搜索效率基本相当,不会出现大幅波动,而且基于索引的顺序扫描时,也可以利用双向指针快速左右移动,效率非常高。因为,B+树索引被广泛应用于数据库、文件系统等场景。
2、Hash索引
哈希索引就是采用一定的哈希算法,把键值换算成新的哈希值,检索时不需要类似B+树那样从根节点到叶子节点逐级查找,只需一次哈希算法即可立刻定位到相应的位置,速度非常快。
3、两者的比较
如果是等值查询,那么哈希索引明显有绝对优势,因为只需要经过一次算法即可找到相应的键值,前提是键值都是唯一的。如果键值不是唯一的,就需要先找到该键所在位置,然后再根据链表往后扫描,知道找到对应的数据。
如果是范围查询检索,这时候哈希索引就毫无用武之地了,因为原先是有序的键值,经过哈希算法后,有可能变成不连续的了,就没办法再利用索引完成范围查询;也没办法利用哈希索引完成排序,以及like这样的部分模糊查询。哈希索引也不支持多列联合索引的最左匹配规则。
B+树索引的关键字检索效率比较平均,不像B树那样波动大,在有大量重复键值情况下,哈希索引的效率也是极低的,因此存在哈希碰撞问题。