索引的概览
索引涉及到的内容比较多,先来对索引有个整体的认知。
- 什么情况下创建索引,什么时候不需要索引?
- 索引的种类有哪些?
索引不是万能的
在数据表中的数据行数比较少的情况下,比如不到1000行,是不需要创建索引的。
另外,当数据重复度大,比如高于10%的时候,也不需要对这个字段使用索引。
如果是性别这个字段,就不需要对它创建索引。这是为什么呢?如果你想要在100万行数据中查找其中的50万行(比如性别为男的数据),一旦创建了索引,你需要先访问50万次索引,然后再访问50万次数据表,这样加起来的开销比不使用索引可能还要大。
索引的种类
功能逻辑
- 普通索引
- 唯一索引
- 主键索引
- 全文索引
-
普通索引是基础的索引,没有任何约束,主要用于提高查询效率。
-
唯一索引就是在普通索引的基础上增加了数据唯一性的约束,在一张数据表里可以有多个唯一索引。
-
主键索引在唯一索引的基础上增加了不为空的约束,也就是
NOT NULL+UNIQUE
,一张表里最多只有一个主键索引。 -
全文索引用的不多,MySQL自带的全文索引只支持英文。一般通常可以采用专门的全文搜索引擎,比如ES(ElasticSearch)和Solr。
物理实现
- 聚集索引
- 非聚集索引【我们也把非聚集索引称为二级索引或者辅助索引】
- 聚集索引可以按照主键来排序存储数据,这样在查找行的时候非常有效。
举个例子,如果是一本汉语字典,想要查找“数”这个字,直接在书中找汉语拼音的位置即可,也就是拼音“shu”。这样找到了索引的位置,在它后面就是我们想要找的数据行。
- 非聚集索引涉及到
回表查询
在数据库系统会有单独的存储空间存放非聚集索引,这些索引项是按照顺序存储的,但索引项指向的内容是随机存储的。
也就是说系统会进行两次查找,第一次先找到索引,第二次找到索引对应的位置取出数据行。
非聚集索引不会把索引指向的内容像聚集索引一样直接放到索引的后面,而是维护单独的索引表(只维护索引,不维护索引指向的数据),为数据检索提供方便。
还以汉语字典为例,如果想要查找“数”字,那么按照部首查找的方式,先找到“数”字的偏旁部首,然后这个目录会告诉我们“数”字存放到第多少页,我们再去指定的页码找这个字。
聚集索引指表中数据行按索引的排序方式进行存储,对查找行很有效。只有当表包含聚集索引时,表内的数据行才会按找索引列的值在磁盘上进行物理排序和存储。每一个表只能有一个聚集索引,因为数据行本身只能按一个顺序存储。
聚集索引与非聚集索引的原理不同,在使用上也有一些区别:
- 聚集索引的叶子节点存储的就是我们的数据记录,非聚集索引的叶子节点存储的是数据位置。非聚集索引不会影响数据表的物理存储顺序。
- 一个表只能有一个聚集索引,因为只能有一种排序存储的方式,但可以有多个非聚集索引,也就是多个索引目录提供数据检索。
- 使用聚集索引的时候,数据的查询效率高,但如果对数据进行插入,删除,更新等操作,效率会比非聚集索引低。
这里说一点自己的使用经验:
- 对WHERE子句的字段(也就是在
where x=???
)建立索引,可以大幅提升查询效率。 - 采用聚集索引进行数据查询,比使用非聚集索引的查询效率略高。如果查询次数比较多,还是尽量使用主键索引进行数据查询。
字段个数
除了业务逻辑和物理实现方式,索引还可以按照字段个数进行划分,分成:
- 单一索引
- 联合索引
索引列为一列时为单一索引;多个列组合在一起创建的索引叫做联合索引。
创建联合索引时,我们需要注意创建时的顺序问题,因为联合索引(x, y, z)
和(z, y, x)
在使用的时候效率可能会存在差别。
这里需要说明的是联合索引存在最左匹配原则,也就是按照最左优先的方式进行索引的匹配。比如刚才举例的(x, y, z),如果查询条件是WHERE x=1 AND y=2 AND z=3
,就可以匹配上联合索引;如果查询条件是 WHERE y=2
,就无法匹配上联合索引。
很棒!
还有后续篇,还在整理
加油!