SQL中的索引设计规范——三星索引

索引的原理

首先要明确,我们平时所说的最左匹配,针对的是索引中的列的顺序,与SQL语句WHERE后面跟的条件无关。因为语句中的条件谓词可以随意调整顺序不影响结果,SQL优化器会自动帮我们调整顺序以使用索引。在索引匹配时,遇到范围和模糊匹配时终止。

select name,age,address,phone,email where name = 'Mutou_ren' and address = 'china' and age > 20 and phone like '132%'

对于以上SQL,有索引(address,name,age,phone)
SQL经过优化器的调整可以变成如下,不会带来任何影响(address和name的顺序换了一下)

select name,age,address,phone,email where address = 'china' and name = 'Mutou_ren' and age > 20 and phone like '132%'

在进行所以匹配时,address、name、age均能进行所以匹配,这三个字段将对本次查询的索引片进行过滤。

我们假设表有一千万条记录,经过以上三个索引字段的过滤,我们只需要扫描1万行索引记录。

由于存在字段email不存在索引记录中,因此在扫描这一万行索引记录时,会拿到主键然后去表记录中查找记录,即所谓的回表,由于拿到的主键无法保证连续,因此每次回表都可以看成一次随机访问,随机访问的成本远远大于顺序访问,回表造成的随机访问是性能开销的大头。

再来看索引(address,name,age,phone),虽然由于age的范围查询导致索引中的phone无法参与索引片的过滤,但由于where谓词中存在phone,在扫描索引片然后进行回表查询时,phone能够起到过滤的作用,对于不满足的条件的回表进行过滤,从而减少回表次数。因此即使最左匹配没有匹配到,但所有出现在where谓词中的索引字段对于查询效率都存在着提升作用

索引(无论聚簇还是辅助)是基于B+树的(这里仅针对Mysqlinnodb引擎),对于非叶子节点,以目前的硬件来讲基本是可以全部放在内存中的,我们不考虑这部分的访问时间,仅对可能放在磁盘上的叶子节点的访问进行评估。
由于索引是存在顺序的,因此在索引扫描时,可以看作只有第一条索引的访问是随机读,后面的都是顺序读。而根据辅助索引拿到的主键可能是不连续的,因此每次回表都可以看成一次随机读。随机读的开销远远大于顺序读的开销(可达千倍)

索引的设计

有了以上的概念,我们可以提出索引中的三星准则,我们按重要程度来讲

  1. 第三星
    对于要查询的所有字段,全都添加到索引中,这里不考虑顺序。
    索引中包含全部的要查询内容,可以完全避免回表查询,将过滤掉绝大部分的随机读访问,对性能的提升很明显。但会导致索引的增大,极端情况与表记录完全一致
  2. 第一星
    根据where中谓词,最小化要扫描的索引片。将范围查询的索引字段放在索引的后面,等值的放在前面。要扫描的索引记录少即代表了可能回表的次数的减少
  3. 第二星
    利用索引的有序性避免排序。对于where a = 1 and b = 1 order by c的语句,索引(a,b,c)中对于a = 1 and b = 1的记录已经是按照c进行排序了,因此这时查询可以不需要再进行额外的排序直接返回。

由于目前排序的成本越来越低,在索引设计时,已优先满足第三星,第一星为准。

优化

对于设计阶段的索引设计,可以按照三星标准来设计,对于已经存在的系统进行索引优化时,我们可以参照BQ法

  1. 在已有的索引上增加where谓词中的字段,形成索引过滤,尽量减少回表次数,形成半宽索引
  2. 对所有的查询字段添加在已有的索引中,做到0回表,形成宽索引
  3. 按照三星准则设计新的索引

索引一定快吗?

如果记录比较少,全表扫描可能会比索引更快。
因为全表扫描是顺序的,且扫描一次即可。而走索引可能会产生回表造成的随机读。

对于连接查询

Mysqlinnodb引擎中,连接查询走的是循环嵌套的方式,即先查出驱动表的符合条件的记录,然后再根据驱动表的记录对嵌套表进行扫描过滤。
驱动表进行驱动嵌套表时,每一条记录的驱动我们都可以看做是一次随机读操作,因此就有我们平时所说的小表驱动大表的优化准则,如我们常说的inexists哪个效率高?
in是内表驱动外表,而exists是外表驱动内表,那个表是驱动表就先查哪个表,因此驱动表记录越少,造成的随机读次数就越少。因此我们可以知道in适合内表结果集少的情况,而exists恰恰相反。

发布了98 篇原创文章 · 获赞 9 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Mutou_ren/article/details/103995150