单表查询sql笔记

举报
ys6687323 发表于 2021/06/30 14:35:09 2021/06/30
【摘要】 单表查询sql的执行,大体上可以分为两步。“二级索引find”和“回表select”。“二级索引find”。有两层含义,一方面是利用二级索引去找,另一方面是利用索引进行过滤(即索引条件下推)。因此正确利用索引也有两层含义,一是利用的索引长度越多越好,二是经过索引find之后,能过滤掉的数据越多越好。“回表select”。因为二级索引毕竟包含的字段列有限,如果我们select的字段不能被索引全...

单表查询sql的执行,大体上可以分为两步。“二级索引find”和“回表select”。

“二级索引find”。

有两层含义,一方面是利用二级索引去找,另一方面是利用索引进行过滤(即索引条件下推)。

因此正确利用索引也有两层含义,一是利用的索引长度越多越好,二是经过索引find之后,能过滤掉的数据越多越好。

“回表select”。

因为二级索引毕竟包含的字段列有限,如果我们select的字段不能被索引全包含,在“二级索引find”结束后,根据得到的主键id,需要去一级索引上查询所需的列。这个过程叫做回表。而“二级索引find”阶段得到的主键id并非有序的,意味着回表是一个随机IO的过程,也就注定了回表是一个成本较高的操作。这也就是为什么有时候mysql宁愿全表扫描也不愿走索引的原因。

索引条件下推的出现就是为了节省回表的成本。

当然,如果我们最终select出来的字段能够被二级索引完全包含,“二级索引find”阶段之后,就不需要进行回表操作,这就是索引覆盖。当出现索引覆盖时,执行计划中Extra列将会通过Using index告诉我们。

回到我们的sql中,表中明明存在与查询条件极度匹配的联合索引(period_year、period_month、user_je_source_name、status),但是mysql却不用,这说明了什么?

说明了period_year、period_month、user_je_source_name、status这些条件并不具备很高的区分度,真正具有区分度的其实是在employee_number、can_auto_push和is_delete当中!

通过控制变量法,对employee_number、can_auto_push和is_delete取不同值时的数据量对比,发现当is_delete分别取0和1时,数据量差别极大。 在这里插入图片描述

可以看到,对于is_delete字段,取值1时,数据量在50w+,取值0时,数据量在1000+。

而我们所要查询的正是is_delete=0的数据。

结合我们第二阶段对执行计划的解读。最终可以确定此sql执行时间过长的瓶颈点就在回表。

该sql只想查询is_delete=0对应的1000+条数据,获取这些数据可能几次回表就能得到。但是通过“索引find”阶段,我们并不能对is_delete字段进行过滤,导致“索引find”阶段会得到50w+的id,然后对这50w+的id进行回表。回表后通过Using where对is_delete字段进行过滤。

整个过程慢就慢在回表。


【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。