Mysql索引优化

44 阅读3分钟

想一下,我们要在一本书里快速找到一篇文章,怎么做呢?就是找到目录,目录上有文章标题和对应页码,根据页码可以快速帮我们找到想要的文章。试想一下,如果没有目录的话你在去查找就很难了,你要从头开始往后查找,这样效率就会很低了,该现象在sql中亦是如此。我们把一张表比喻成一本书,而sql查找的内容就是我们要找的文章,我们想要快速找到指定文章就需要借助目录了,在mysql中可以充当目录的角色就是索引,它是帮助Mysql高效获取数据的排好序数据结构

image.png

从上图可以看到SQL及索引优化是最好的,成本也是最低的!

知道了索引的重要性,那么它是如何提高查询效率的呢?首先不得不从它的底层数据结构说起。

Mysql目前普遍使用Innodb存储引擎(表设置),它的底层数据结构是B+树,那么这种数据结构有何优点呢。

  1. 最大的优点就是树的高度低,这样可以减少磁盘的I/O操作(采用了页节点,页大小默认为16kb),树的高度取决于一个页节点当中存放的索引元素多少,这也是mysql不用B树的原因。
  2. 在树的同一行高度中,是有序的,从左到右依次递增。
  3. 相比于B树来说,数据(聚集索引-叶节点包含了完整的数据记录:在Innodb引擎存放所在行数据。非聚集索引:在Innodb引擎中存放主键ID;在Myisam引擎中存储的是所在行磁盘路径)只在叶子节点存储。非叶子节点只存储索引(冗余),这样可以放更多的索引。叶子节点用双向指针连接,提高区间访问性能(范围查找)。

介绍完数据结构后,简单介绍下如何使用它。

一般情况下我们会建立联合索引,联合索引遵循最左前缀原则,如下图所示,显示的是一个有name/age/position组成的一个主键联合索引。

联合索引.png 在该图中可以看到在同一行中,会先比较name的顺序,name相同才会比较age的数据,并排好序。这也就解释了为什么sql条件只有age/position为什么无法走索引,由这个结构所决定。(这个结构图一定要牢记于心,很重要)

使用总结.png 最后说下索引优化原则,如下:

  1. 全值匹配:联合索引尽可能全覆盖。
  2. 最左前缀原则。
  3. 不在索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描。
  4. 存储引擎不能使用索引中范围条件右边的列。
  5. 尽量使用覆盖索引,减少select* 语句。
  6. mysql在使用不等于的时候无法使用索引。
  7. is null/is not null一般情况下也无法使用索引。
  8. like以通配符开头不走索引(like '%Lei'),可通过覆盖索引优化到index级别。
  9. 字符串不加单引号导致索引失效。
  10. 少用or或者in。可能走索引也可能不走索引。
  11. 大范围拆小范围。