MySQL表上做查询慢出现状况爱可生

问题

我们有一个SQL,用于找到没有主键/唯一键的表,但是在MySQL5.7上运行特别慢,怎么办?

实验

我们搭建一个MySQL5.7的环境,此处省略搭建步骤。

写个简单的脚本,制造一批带主键和不带主键的表:

执行一下脚本:

现在执行以下SQL看看效果:

执行了16.80s,感觉是非常慢了。

现在用一下DBA三板斧,看看执行计划:

感觉有点惨,由于information_schema.columns是元数据表,没有必要的统计信息。

那我们来showwarnings看看MySQL改写后的SQL:

我们格式化一下SQL:

可以看到MySQL将

selectfromAwhereA.xnotin(selectxfromB)//非关联子查询

转换成了

selectfromAwherenotexists(select1fromBwhereB.x=a.x)//关联子查询

如果我们自己是MySQL,在执行非关联子查询时,可以使用很简单的策略:

selectfromAwhereA.xnotin(selectxfromBwhere...)//非关联子查询:1.扫描B表中的所有记录,找到满足条件的记录,存放在临时表C中,建好索引2.扫描A表中的记录,与临时表C中的记录进行比对,直接在索引里比对,

而关联子查询就需要循环迭代:

selectfromAwherenotexists(select1fromBwhereB.x=a.xand...)//关联子查询扫描A表的每一条记录rA:扫描B表,找到其中的第一条满足rA条件的记录。

显然,关联子查询的扫描成本会高于非关联子查询。

我们希望MySQL能先缓存子查询的结果(缓存这一步叫物化,MATERIALIZATION),但MySQL认为不缓存更快,我们就需要给予MySQL一定指导。

可以看到执行时间变成了0.67s。

整理

我们诊断的关键点如下:

1.对于information_schema中的元数据表,执行计划不能提供有效信息。

2.通过查看MySQL改写后的SQL,我们猜测了优化器发生了误判。

3.我们增加了hint,指导MySQL正确进行优化判断。

但目前我们的实验仅限于猜测,猜中了万事大吉,猜不中就无法做出好的诊断。




转载请注明:http://www.aierlanlan.com/rzdk/5212.html

  • 上一篇文章:
  •   
  • 下一篇文章: 没有了