数据库索引

数据库索引简介

数据库索引的定义

数据库索引是一种数据结构。经过增长额外的写操做和存储空间来维护数据库索引,能够提升从数据库中读取数据的速度。经过索引,不须要搜索数据库的每一条记录,就能够快速地定位到特定的数据。索引能够建在在表中某一个字段或多个字段之上。总而言之:数据库索引是一种数据结构mysql

数据库索引的做用

  1. 用于支持快速地查找到数据sql

    • 若没有索引,一般须要遍历全部记录才能找到相应地数据(O(N));而经过索引,通常只须要O(log(N))次就能够定位到数据,提升了查找效率
  2. 管理数据库约束数据库

    • 索引一般还会被用于管理数据库约束,例如UNIQUE, EXCLUSION, PRIMARY KEY 和 FOREIGN KEY。当一个索引被定义为UNIQUE时,数据库同时建立一个隐式的约束。

Clustered Index & Non-clustered Index

Clustered Index(汇集索引/聚簇索引)

汇集索引是指数据库表行中数据的物理顺序与键值的逻辑(索引)顺序相同。一个表只能有一个汇集索引,由于一个表的物理顺序只有一种状况,因此,对应的汇集索引只能有一个。若是某索引不是汇集索引,则表中的行物理顺序与索引顺序不匹配,与非汇集索引相比,汇集索引有着更快的检索速度。以下图,叶节点中直接包含了具体数据。
汇集索引数据结构

Non-clustered Index(非汇集索引/非聚簇索引)

与汇集索引不一样,非汇集索引的逻辑顺序与磁盘上行的物理存储顺序不一样。磁盘上的数据能够随意分布,而经过非汇集索引,能够在逻辑上为数据排序。以下图,叶节点没有包含具体的数据,而是包含了一个指向具体数据的指针。
非汇集索引函数

区别

当索引经过二叉树的形式进行描述时,咱们能够这样区分汇集与非汇集索引的区别:汇集索引的叶节点就是最终的数据节点,而非汇集索引的叶节仍然是索引节点,但它有一个指向最终数据的指针。工具

数据库索引的实现

常见的数据库索引实现有性能

  1. 平衡树(B树)
  2. B+树
  3. Hashes(哈希)

B树,B+树

参考B-tree wikiB+ tree wiki优化

Mysq中的索引

MySQL数据库支持多种索引类型,如B+ Tree索引,哈希索引,全文索引等等。下面只分析B+ Tree索引。spa

MyISAM索引实现

MyISAM引擎使用B+Tree做为索引实现,而且全部的索引都是非汇集索引
下图是主键索引:
MyIASAM主键索引
若在Col2上创建辅助索引,其依然是一个非汇集索引,与主键索引相似:
MyIASAM辅助索引
MyISAM引擎中,使用索引查找数据时,先经过索引获取到数据的物理地址,而后经过物理地址读取数据。指针

InnoDB索引实现

InnoDB引擎一样使用B+Tree做为索引实现,但与MyISAM不一样,在InnoDB引擎中,主键索引是汇集索引,而辅助索引则是非汇集索引。下图是主键索引:
InnoDDB主键索引
若在Col2上创建辅助索引,则是一个非汇集索引,叶节点的值为数据的主键:
InnoDB辅助索引
在InnoDB中,经过主键索引,能够直接获取到具体的数据;而经过辅助索引,在叶节点获取到的是数据的主键,而后再经过主键索引最终获取到数据。

联合索引/多列索引

在上面的介绍中,咱们主要是针对一个字段创建索引,而实际上,能够创建一个基于多个字段的索引。假设某张表中有a,b,c,d四个字段。如今在a,b,c上创建索引(a,b,c)(注意: a,b,c顺序不一样创建的是不一样的索引)。则索引首先会按a字段排序;在a字段相同的状况下按照b字段排序;在a,b字段相同的状况下按照c字段排序,以此类推。。。

最左前缀匹配原则

当创建联合索引时,该索引的全部最左前缀匹配能够用于优化查找。以上面创建的(a,b,c)索引为例,其全部最左前缀匹配为(a),(a,b),(a,b,c)。即涉及到(a),(a,b),(a,b,c)的查找均可以利用索引(a,b,c),但涉及(a,c)的查找没法利用索引(a,b,c),由于(a,c)不知足最左前缀匹配原则。

前缀索引

前缀索引就是针对字段的“前特定个字符”创建索引,而非对整个字段的值创建索引。显然,由于没有对完整的字段值创建索引,因此这样创建的索引更小,查询更快。MySQL的前缀索引能有效减少索引文件的大小,提升索引的速度。可是前缀索引也有它的坏处:MySQL 不能在 ORDER BY 或 GROUP BY 中使用前缀索引,也不能把它们用做覆盖索引(Covering Index)。
能够经过下面的预发创建前缀索引:

ALTER TABLE table_name ADD KEY(column_name(prefix_length));

覆盖索引

覆盖索引(covering index)指一个查询语句的执行只须要从辅助索引中就能够获得查询记录,而不须要查询汇集索引中的记录。也能够称之为实现了索引覆盖。辅助索引不包含一整行的记录,所以能够大大减小IO操做。覆盖索引是mysql dba经常使用的一种SQL优化手段。

Mysql中高性能的索引策略

独立的列

若是查询中的列不是独立的,则MySQL就不会使用索引。“独立的列”是指索引列不能是表达式的一部分,也不能是函数的参数。所以应该简化WHERE条件,始终将索引列单独放在比较符号的一侧

SELECT actor_id FROM sakila.actor WHERE actor_id + 1 = 5;(没法使用actor_id列的索引)
SELECT actor_id FROM sakila.actor WHERE actor_id = 4;(可使用actor_id列的索引)

前缀索引和索引选择性

有时候须要索引很长的字符列,这会使索引变得大且慢。一般能够索引开始的部分字符,这样能够大大节约索引空间,从而提升索引效率。但这样也会下降索引的选择性。索引的选择性是指,不重复的索引值(也称为基数)和数据的记录总数(#T)的比值,范围从1/#T到1之间。索引的选择性越高则查询效率越高。惟一索引的选择性是1,这是最好的索引选择性,性能也是最好的。

通常状况下某个列的前缀的选择性也是足够高的,足以知足查询性能。对于BLOB,TEXT或很长的VARCHAR类型的列,必须使用前缀索引,由于MySQL不容许索引这些列的完整长度。一般状况,咱们应该尽可能使前缀的“基数”接近于完整列的“基数”。

前缀索引的缺点 : MySQL没法使用前缀索引作ORDER BY和GROUP BY,也没法使用前缀索引作覆盖扫描。


多列索引

在多个列上创建独立的单列索引大部分状况下并不能提升MySQL的查询性能。此时应该考虑创建多列索引。


选择合适的索引列顺序(针对B-Tree索引)

当不须要考虑排序和分组时,一般将选择性最高的列放到索引最前列。
有时可能须要根据那些运行频率最高的查询来调整索引列的顺序。


覆盖索引

若是一个索引包含(或者说是覆盖)全部须要查询的字段的值,咱们就称为“覆盖索引”,使用覆盖索引可以极大地提升性能。


使用索引来作排序

MySQL可使用同一个索引既知足排序,又用于查找行。所以,若是可能,涉及索引时应该尽量地同时知足这两种任务。只有当索引的列顺序和ORDER BY子句的顺序彻底一致,而且索引列的排序方向(倒序或正序)都同样时,MySQL才能使用索引来对结果排序。若是查询须要关联多张表,则只有当ORDER BY子句引用的字段所有为第一个表时,才能使用索引作排序。ORDER BY子句和查找型查询的限制是同样的:须要知足索引的最左前缀需求;不然,MySQL都须要执行排序操做,而没法利用索引排序。


冗余和重复索引

重复索引是指在相同的列上按照相同的顺序建立相同类型的索引,应该避免这样建立的重复索引,发现后也应该当即移除。MySQL容许在相同列上建立多个索引。MySQL须要单独维护重复的索引,而且优化器在优化查询的时候也须要逐个地进行考虑,这会影响性能。

冗余索引和重复索引又一些不一样。若是建立了索引(A,B),再建立索引(A)就是冗余索引,由于这只是前一个索引的前缀索引。大多数状况下,都不须要冗余索引,应该尽量扩展已有的索引而不是建立新索引。但也有时候出于性能方面的考虑须要冗余索引,由于扩展已有的索引会致使其变得太大,从而影响其余使用该索引的查询的性能。


未使用的索引

若一个索引再也不被使用,则应该考虑删除。能够经过一些工具找到未使用的索引,如Percona Toolkit中的pt-index-usage

相关文章
相关标签/搜索