ZhouXiangの博客 后端工程师&机器学习爱好者

MySQL索引简介

2019-02-15

MySQL索引简介。

什么是索引

索引是存储引擎中用于快速找到记录的一种数据结构。在MySQL中被称为键,KEY。

索引的优点

  • 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。
  • 可以大大加快数据的检索速度,这也是创建索引的最主要的原因。
  • 可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。
  • 在使用分组和排序 子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。
  • 通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。
  • 索引可以将随机I/O变成顺序I/O。
  • 索引可以帮助服务器避免排序和临时表。

索引的缺点

  • 创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。
  • 索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。
  • 当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。

索引的应用注意事项

常见的索引原则

  • 唯一性索引的值是惟一的
  • 为经常需要排序、分组和联合操作的字段建立索引
  • 为常做查询条件的字段建立索引
  • 限制索引的数目
  • 如果索引的值很长,那么查询速度会受到影响
  • 如果索引字段的值很长,最好使用值前缀做索引
  • 删除不再使用或者很少使用的索引
  • 最左前缀匹配原则
  • 尽量选择区分度高的列做索引
  • 索引列不能参与计算,保持列的干净
  • 尽量扩展索引而不是新建索引

应该添加索引的场景

  • 在经常需要搜索的列上,可以加快搜索的速度;
  • 在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构;
  • 在经常用在连接的列上,这 些列主要是一些外键,可以加快连接的速度;
  • 在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的;
  • 在经常需要排序的列上创 建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间;
  • 在经常使用在WHERE子句中的列上面创建索引,加快条件的判断速度。

不应该添加索引的场景

  • 对于那些在查询中很少使用或者参考的列不应该创建索引。这是因 为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。
  • 对于那 些只有很少数据值的列也不应该增加索引。这是因为,由于这些列的取值很少,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。
  • 对于那些定义为text, image和bit数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少。
  • 当修改性能远远大于检索性能时,不应该创建索 引。这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因此,当修改性能远远大于检索性能时,不应该创建索引。

索引大类别

  • B-Tree索引
  • 哈希索引
  • 全文索引

B-Tree索引

B+树索引的本质就是B+树在数据库中的实现。但是B+索引在数据库中有一个特点是高扇出性,因此在数据库中,B+数的高度一般为2-4层,意味着查找某一键值的行记录时最多需要2-4次I/O。数据库中的B+树索引分为聚簇索引和非聚簇索引。二者内部结构均为B+树,即高度平衡的,叶子节点存放数据。而二者不同的是,聚簇索引的叶子节点存放一整行的信息。不同存储引擎以不同的方式使用B-Tree索引,性能也各有不同。MyIASM索引通过数据的物理位置引用被索引的行,而InnoDB则根据主键引用被索引的行。B-Tree索引适用于全键值、键值范围或键前缀查找。其中键前缀查找只适用于根据最左前缀的查找。

哈希索引

哈希索引基于哈希表实现,只有精确匹配索引所有列的查询才有效。哈希索引将所有的哈希码存储在索引中,同时在哈希表中保存指向每个数据行的指针。因为索引本身只需存储对应的哈希值,所以索引的结构十分紧凑,这也让哈希索引查找速度极快。然而,哈希索引也有一定的限制:

  • 哈希索引中只包含哈希值和行指针,而不存储字段值,所以不能使用索引中的值来避免读取行。
  • 哈希索引数据并不是按照索引值排序存储,所以无法用于排序。
  • 不支持部分索引匹配查找
  • 只支持等值比较查询
  • 如果哈希 冲突很严重,一些索引维护代价也会很高

全文索引

全文索引是一种特殊类型的索引,它查找的是文本中的关键词,而不是直接比较索引中的值。全文索引和其他几类索引的匹配方式不同。需要注意很多细节,例如停用词、词干和复数、布尔搜索等。全文索引更类似于搜索引擎做的事情,而不是简单的where条件匹配。

索引小类别

  • 聚簇索引
  • 辅助索引
  • 覆盖索引
  • 联合索引

聚簇索引

InnoDB存储引擎是索引组织表,即表中数据按照主键顺序存放。如果没有定义主键,InnoDB会选择一个唯一的非空索引代替。如果没有这样的索引,InnoDB会隐式定义一个主键作为聚簇索引。通常来讲,聚簇索引就是按照每张表的主键构造一课B+树,同时叶子节点中存放的即为整张表的行记录数据,也将聚簇索引的叶子结点称为数据页。同B+数一样,每个数据页通过一个双向链表连接。由于实际的数据页只能按照一课B+数进行排序,因此每张表只能拥有一个聚簇索引。

聚簇索引的优点:

  • 相关数据关联,这样从磁盘读取少量数据页就能获得完整的目标数据,否则将会导致大量I/O
  • 聚簇索引查找速度优于非聚簇索引
  • 使用覆盖索引扫描的查询可以直接使用页节点中的主键

聚簇索引的缺点:

  • 聚簇索引在密集型I/O中性能优势明显,但是如果数据都在内存中,优势全无
  • 插入速度严重依赖插入顺序。如果不是按照主键顺序加载数据,最好先使用OPTIMIZE TABLE命令重新组织表
  • 更新聚簇索引列的代价很高
  • 基于聚簇索引的表在插入新行或主键被更新导致需要移动行的时候,可能面临页分裂的情况。页分裂会导致表占用更多的磁盘空间
  • 聚簇索引可能会导致全表扫描变慢,尤其是行比较稀疏,或者由于页分裂导致数据存储不连续的时候
  • 二级索引(非聚簇索引)可能极大

辅助索引(非聚簇索引)

辅助索引也称非聚簇索引,叶子节点并不包含行记录的全部数据。叶子节点除了键值以外,每个叶子节点中的索引行中还包括了一个书签。该书签用来告诉InnoDB存储引擎可以找到与索引的书签就是相应行的聚集索引键。

非聚集索引和聚集索引一样,同样是采用平衡树作为索引的数据结构。索引树结构中各节点的值来自于表中的索引字段,假如给user表的name字段加上索引,那么索引就是由name字段中的值构成,在数据改变时,DBMS需要一直维护索引结构的正确性。如果给表中多个字段加上索引,那么就会出现多个独立的索引结构,每个索引(非聚集索引)互相之间不存在关联。如下图:


每次给字段建一个新索引,字段中的数据就会被复制一份出来,用于生成索引。因此,给表添加索引,会增加表的体积,占用磁盘存储空间。
非聚集索引和聚集索引的区别在于,通过聚集索引可以查到需要查找的数据,而通过非聚集索引可以查到记录对应的主键值,再使用主键的值通过聚集索引查找到需要的数据,如下图:

不管以任何方式查询表,最终都会利用主键通过聚集索引来定位到数据,聚集索引(主键)是通往真实数据所在的唯一路径。然而,有一种例外可以不使用聚集索引就能查询出所需要的数据, 这种非主流的方法称之为「覆盖索引」查询,也就是平时所说的复合索引或者多字段索引查询。 文章上面的内容已经指出,当为字段建立索引以后,字段中的内容会被同步到索引之中,如果为一个索引指定两个字段,那么这个两个字段的内容都会被同步至索引之中。

覆盖索引

InnoDB支持覆盖索引,即从辅助索引中就可以得到查询的记录,而不需要查询聚簇索引的的记录。使用覆盖索引的好书是辅助索引不包含整行记录的所有信息,故其大小要远小于聚簇索引,因此可以减少大量I/O操作。

覆盖索引的好处:

  • 索引条目通常远小于数据行大小,所以如果只需要读取索引,那MySQL就会极大地减少数据访问量。
  • 因为索引是按照列值顺序存储,对于I/O密集型的范围查询会比随机从磁盘读取每一行数据的I/O要少的多。
  • 覆盖索引在一定程度上可以避免主键索引的二次查询。

联合索引

联合索引是指对表上的多个列进行索引。联合索引的创建方法与单个索引创建的方法一样,不同之处仅在于有多个索引列。本质上来看,联合索引也是一颗B+树,不同的是,联合索引的键值数量不是1而是大于等于2。联合索引的一个好处是已经对键值进行排序,可以避免多一次的排序操作。在设计实现联合索引时,应该着重考虑索引的顺序,一般来说,将选择性最高的列放在前面较好。


上一篇 git常见操作

下一篇 Linux常见命令

Comments

Content