索引

索引,在 MySQL 中也叫作键(key),是存储引擎用于快速找到记录的一种数据结构。索引是数据库优化中最常用也是最重要的手段之一,通过索引通常可以帮助用户解决大多数的 SQL 性能问题。

索引是在 MySQL 的存储引擎层中实现的,而不是在服务器层实现的。所以每种存储引擎的索引都不一定完全相同,也不是所有的存储引擎都支持所有的索引类型。

MySQL 目前提供了以下 4 种索引:

  • B-Tree 索引:最常见的索引类型,大部分引擎都支持 B 树索引。

  • HASH 索引:只有 Memory 引擎支持,使用场景简单。

  • R-Tree 索引(空间索引):空间索引是 MyISAM 的一个特殊索引类型,主要用于地理空间数据类型。

  • Full-text(全文索引):全文索引也是 MyISAM 的一个特殊索引类型,主要用于全文索引,InnoDB 从MySQL 5.6 版本开始提供对全文索引的支持。

MySQL 目前不支持函数索引,但是能对列的前面某一部分进行索引,例如标题 title 字段,可以只取 title 的前 10 个字符进行索引,这个特性可以大大缩小索引文件的大小,但前缀索引也有缺点,在排序 Order By 和分组 Group By 操作的时候无法使用。

索引MyISAMInnoDBMemory

B-Tree索引

支持

支持

支持

HASH索引

不支持

不支持

支持

R-Tree索引

支持

不支持

不支持

Full-text索引

支持

支持

不支持

表中的索引越多,插入的速度越慢。一般来说,增加新索引会导致 INSERT、UPDATE、DELETE 等操作的速度变慢,特别是当新增索引后达到了内存瓶颈的时候。

索引使用三原则

在 MySQL 中,大多数情况下都会使用 B-tree 索引,其他类型的索引大多只适用于特殊的目的。如果在合适的场景中使用索引,将大大缩短查询的响应时间。

在选择索引和编写利用这些索引的查询时,有如下三个原则始终需要记住:

  • 单行访问是很慢的,特别是在机械硬盘中(SSD 的随机 I/O 要快很多,不过这一点仍然成立)。如果服务器从存储中读取一个数据块只是为了获取其中一行,那么就浪费了很多工作。最好读取的块中能包含尽可能多的所需要的行。

  • 按顺序访问范围数据是很快的有两个原因:

    • 第一,顺序 I/O 不需要多次磁盘寻道,所以比随机 I/O 要快很多(特别是对于机械硬盘)

    • 第二,如果服务器能够按需顺序读取数据,那么就不再需要额外的排序操作,并且 GROUP BY 查询也无须再做排序和将行按组进行聚合计算了

  • 索引覆盖查询是很快的。如果一个索引包含了查询需要的所有列,那么存储引擎就不需要再回表查找行,这避免了大量的单行访问。

总的来说,编写查询语句时应该尽可能选择合适的索引以避免单行查找,尽可能地使用数据内部顺序从而避免额外的排序操作,并尽可能地使用索引覆盖查询。

如何判断索引是否合理

  1. 首先,按响应时间来对查询进行分析。找出那些消耗时间最长的查询或者那些给服务器带来最大压力的查询

  2. 然后,检查这些查询的 schema、SQL 语句和索引结构,判断是否有查询扫描了太多的行,是否做了很多额外的排序或者使用了临时表,是否使用随机 I/O 访问数据,或者是否有太多回表查询查询那些不在索引中的列的操作。

  3. 如果一个查询无法从所有可能的索引中获益,则应该看看是否可以创建一个更合适的索引来提升性能。如果不行,还可以看看是否可以重写该查询,将其转化成一个能够高效利用现有索引或者新创建索引的查询。

最后更新于