想一下,我们要在一本书里快速找到一篇文章,怎么做呢?就是找到目录,目录上有文章标题和对应页码,根据页码可以快速帮我们找到想要的文章。试想一下,如果没有目录的话你在去查找就很难了,你要从头开始往后查找,这样效率就会很低了,该现象在sql中亦是如此。我们把一张表比喻成一本书,而sql查找的内容就是我们要找的文章,我们想要快速找到指定文章就需要借助目录了,在mysql中可以充当目录的角色就是索引,它是帮助Mysql高效获取数据的排好序的数据结构。
从上图可以看到SQL及索引优化是最好的,成本也是最低的!
知道了索引的重要性,那么它是如何提高查询效率的呢?首先不得不从它的底层数据结构说起。
Mysql目前普遍使用Innodb存储引擎(表设置),它的底层数据结构是B+树,那么这种数据结构有何优点呢。
- 最大的优点就是树的高度低,这样可以减少磁盘的I/O操作(采用了页节点,页大小默认为16kb),树的高度取决于一个页节点当中存放的索引元素多少,这也是mysql不用B树的原因。
- 在树的同一行高度中,是有序的,从左到右依次递增。
- 相比于B树来说,数据(聚集索引-叶节点包含了完整的数据记录:在Innodb引擎存放所在行数据。非聚集索引:在Innodb引擎中存放主键ID;在Myisam引擎中存储的是所在行磁盘路径)只在叶子节点存储。非叶子节点只存储索引(冗余),这样可以放更多的索引。叶子节点用双向指针连接,提高区间访问性能(范围查找)。
介绍完数据结构后,简单介绍下如何使用它。
一般情况下我们会建立联合索引,联合索引遵循最左前缀原则,如下图所示,显示的是一个有name/age/position组成的一个主键联合索引。
在该图中可以看到在同一行中,会先比较name的顺序,name相同才会比较age的数据,并排好序。这也就解释了为什么sql条件只有age/position为什么无法走索引,由这个结构所决定。(这个结构图一定要牢记于心,很重要)
最后说下索引优化原则,如下:
- 全值匹配:联合索引尽可能全覆盖。
- 最左前缀原则。
- 不在索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描。
- 存储引擎不能使用索引中范围条件右边的列。
- 尽量使用覆盖索引,减少select* 语句。
- mysql在使用不等于的时候无法使用索引。
- is null/is not null一般情况下也无法使用索引。
- like以通配符开头不走索引(like '%Lei'),可通过覆盖索引优化到index级别。
- 字符串不加单引号导致索引失效。
- 少用or或者in。可能走索引也可能不走索引。
- 大范围拆小范围。