关于sql:一次非常有意思的-SQL-优化经历-从-30248271s-到-0001s

4次阅读

共计 1498 个字符,预计需要花费 4 分钟才能阅读完成。

我的公众号:MarkerHub,Java 网站:https://markerhub.com

更多精选文章请点击:Java 笔记大全.md

小 Hub 领读:

数据量少的时候看不出区别,量大差异显著,文末的 4 点总结你应该去看一下,或者对你有帮忙!


  • 风过无痕
  • https://www.cnblogs.com/tangy…

场景

用的数据库是 mysql5.6,上面简略的介绍下场景

课程表:

数据 100 条

学生表:

数据 70000 条

学生成绩表 SC:

数据 70w 条

查问目标:

查找语文考 100 分的考生

查问语句:

执行工夫:30248.271s

为什么这么慢?先来查看下查问打算:

发现没有用到索引,type 全是 ALL,那么首先想到的就是建设一个索引,建设索引的字段当然是在 where 条件的字段。

先给 sc 表的 c_id 和 score 建个索引

再次执行上述查问语句,工夫为: 1.054s

快了 3w 多倍,大大缩短了查问工夫,看来索引能极大水平的进步查问效率,看来建索引很有必要,很多时候都遗记建索引了,数据量小的的时候压根没感觉,这优化感觉挺爽。

然而 1s 的工夫还是太长了,还能进行优化吗,认真看执行打算:

查看优化后的 sql:

补充:这里有网友问怎么查看优化后的语句

办法如下:

在命令窗口执行

有 type=all

依照我之前的想法,该 sql 的执行的程序应该是先执行子查问

耗时:0.001s

失去如下后果:

而后再执行

耗时:0.001s

这样就是相当快了啊,Mysql 居然不是先执行里层的查问,而是将 sql 优化成了 exists 子句,并呈现了 EPENDENT SUBQUERY,

mysql 是先执行外层查问,再执行里层的查问,这样就要循环 70007*11=770077 次。

那么改用连贯查问呢?

这里为了从新剖析连贯查问的状况,先临时删除索引 sc_c_id_index,sc_score_index

执行工夫是:0.057s

效率有所提高,看看执行打算:

这里有连表的状况呈现,我猜测是不是要给 sc 表的 s_id 建设个索引

CREATE index sc_s_id_index on SC(s_id);

show index from SC

在执行连贯查问

工夫: 1.076s,居然工夫还变长了,什么起因?查看执行打算:

优化后的查问语句为:

貌似是先做的连贯查问,再执行的 where 过滤

回到后面的执行打算:

这里是先做的 where 过滤,再做连表,执行打算还不是固定的,那么咱们先看下规范的 sql 执行程序:

失常状况下是先 join 再 where 过滤,然而咱们这里的状况,如果先 join,将会有 70w 条数据发送 join 做操,因而先执行 where

过滤是理智计划,当初为了排除 mysql 的查问优化,我本人写一条优化后的 sql

即先执行 sc 表的过滤,再进行表连贯,执行工夫为:0.054s

和之前没有建 s_id 索引的工夫差不多

查看执行打算:

先提取 sc 再连表,这样效率就高多了,当初的问题是提取 sc 的时候呈现了扫描表,那么当初能够明确须要建设相干索引

再执行查问:

执行工夫为:0.001s,这个工夫相当靠谱,快了 50 倍

执行打算:

咱们会看到,先提取 sc,再连表,都用到了索引。

那么再来执行下 sql

执行工夫 0.001s

执行打算:

这里是 mysql 进行了查问语句优化,先执行了 where 过滤,再执行连贯操作,且都用到了索引。

总结

1、mysql 嵌套子查问效率的确比拟低

2、能够将其优化成连贯查问

3、建设适合的索引

4、学会剖析 sql 执行打算,mysql 会对 sql 进行优化,所以剖析执行打算很重要

举荐浏览

Java 笔记大全.md

太赞了,这个 Java 网站,什么我的项目都有!https://markerhub.com

这个 B 站的 UP 主,讲的 java 真不错!

正文完
 0