关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » 网站维护 »一个20秒SQL慢查询优化的经历与处理方案(1)

    一个20秒SQL慢查询优化的经历与处理方案(1)

    2015-09-14 00:00:00 出处:ITJS
    分享

    背景

    前几天在项目上线过程中,发现有一个页面无法正确获取数据,经排查原来是接口调用超时,而最后发现是因为SQL查询长达到20多秒而导致了问题的发生。

    这里,没有高深的理论或技术,只是备忘一下经历和解读一些思想误区。

    复杂SQL语句的构成

    这里不过多对业务功能进行描述,但为了突出问题所在,会用类比的语句来描述当时的场景。复杂的SQL语句可以表达如下:

    SELECT * FROM a_table AS a  LEFT JOIN b_table AS b ON a.id=b.id  WHERE a.id IN (     SELECT DISTINCT id FROM a_table      WHERE user_id IN (100,102,103) GROUP BY user_id HAVING count(id) > 3 ) 

    关联查询

    从上面简化的SQL语句,可以看出,首先进行的是关联查询。

    子查询

    其次,是嵌套的子查询。此子查询是为了找出多个用户共同拥有的组ID。所以语句中的“100,102,103”是根据场景来定的,并且需要和后面“count(id) > 3”的个数对应。简单来说,就是找用户交集的组ID。

    耗时在哪

    假设现在a_table表的数据量为20W,而b_table的数据量为2000W。大家可以想一下,你觉得主要的耗时是在关联查询部分,还是在子查询部分

    (思考空间。。。。)

    (思考空间。。。。 。。。)

    (思考空间。。。。 。。。 。。。)

    问题定位

    对于SQL底层的原理和高深的理论,我暂时掌握不够深入。但我知道可以通过类比和简单的测试来验证是哪一块环节出了问题。

    初步断定

    首先,对于只有一个用户ID时,我会把上面的语句简化成:

    SELECT * FROM a_table AS a  LEFT JOIN b_table AS b ON a.id=b.id  WHERE user_id IN (100) 

    所以,初步断定应该是嵌套的子查询部分占用了大部分的时间。

    再进一步验证

    既然定位到了是嵌套的子查询语句的问题,那又要分为两块待排查的区域:是子查询本身耗时大,还是嵌套而导致慢查询

    结果很容易发现,当我把子查询单独在DB中执行时,是非常快的。所以排除。

    剩下的不言而喻,20秒的慢查询是嵌套引起的。

    但因为处于上线紧急的过程中,为了确保,我快速地验证了我的结论:

    1、将子查询的ID单独执行,并把得到的结果序列手动拼成一段ID,如:1,2,3,4, … , 999

    2、将上面得到的序列ID,手动替换到原来的SQL语句

    3、执行,发现,很快!只用了约150 ms

    Well Done! 准备修复上线!

    解决方案

    线上的问题,很多时间都是在定位问题和分析原因,既然问题找到了,原因也找到了,解决方案不言而喻。代码简单处理即可。

    另外一个需要注意的点

    当前,实际的SQL语句,会比这个更为复杂,但已足以表达问题所在。但在前期,笔者也做了一些SQL的代码。

    因为b_table比a_table大,所以一开始 b_table 左关联 a_table 时,很慢,大概是1秒多,而且数据量是很少的;但若反过来,a_table 左关联 b_table 时,则很快,大概是100毫秒。

    所以,又发现一个有趣的现象:

    大表 左关联 小表,很慢;小表 左关联 大表,很快。

    当然,这些我们理论上都知道,但实际开发会忘却。又或者一开始两个表都为空时,而又没考虑到后期这两个表增长的速度时,日后就会埋下坑了。

    总结

    首先,嵌套的子查询是很慢的。

    原因,我还没仔细去研究,但在下班的路上和我的同事交流时,他说曾经看过这方面相关的书籍,是说每一次的子查询都会产生一个SQL语句,所以就N次查询了。而另外一位资深的QA同事则跟我说,应该是M*N的问题。

    其次,我一开始使用嵌套子查询,是存在这样一个误区:我觉得将这些操作交给MySQL自身来处理会更高效,毕竟DB内部会有良好的机制来执行这些查询由。

    然后,实际表白,我错了。因为这不是简单的合并MC批量查询。

    当我们决定使用一些底层的技术时,只有当我们理解透彻了,才能使用更为恰当。而因为无知就断定工具、框架、底层无所不能时,往往就会中招。

    博文出处:http://my.oschina.net/dogstar/blog/398879

    背景

    前几天在项目上线过程中,发现有一个页面无法正确获取数据,经排查原来是接口调用超时,而最后发现是因为SQL查询长达到20多秒而导致了问题的发生。

    这里,没有高深的理论或技术,只是备忘一下经历和解读一些思想误区。

    复杂SQL语句的构成

    这里不过多对业务功能进行描述,但为了突出问题所在,会用类比的语句来描述当时的场景。复杂的SQL语句可以表达如下:

    SELECT * FROM a_table AS a  LEFT JOIN b_table AS b ON a.id=b.id  WHERE a.id IN (     SELECT DISTINCT id FROM a_table      WHERE user_id IN (100,102,103) GROUP BY user_id HAVING count(id) > 3 ) 

    关联查询

    从上面简化的SQL语句,可以看出,首先进行的是关联查询。

    子查询

    其次,是嵌套的子查询。此子查询是为了找出多个用户共同拥有的组ID。所以语句中的“100,102,103”是根据场景来定的,并且需要和后面“count(id) > 3”的个数对应。简单来说,就是找用户交集的组ID。

    耗时在哪

    假设现在a_table表的数据量为20W,而b_table的数据量为2000W。大家可以想一下,你觉得主要的耗时是在关联查询部分,还是在子查询部分

    (思考空间。。。。)

    (思考空间。。。。 。。。)

    (思考空间。。。。 。。。 。。。)

    问题定位

    对于SQL底层的原理和高深的理论,我暂时掌握不够深入。但我知道可以通过类比和简单的测试来验证是哪一块环节出了问题。

    初步断定

    首先,对于只有一个用户ID时,我会把上面的语句简化成:

    SELECT * FROM a_table AS a  LEFT JOIN b_table AS b ON a.id=b.id  WHERE user_id IN (100) 

    所以,初步断定应该是嵌套的子查询部分占用了大部分的时间。

    再进一步验证

    既然定位到了是嵌套的子查询语句的问题,那又要分为两块待排查的区域:是子查询本身耗时大,还是嵌套而导致慢查询

    结果很容易发现,当我把子查询单独在DB中执行时,是非常快的。所以排除。

    剩下的不言而喻,20秒的慢查询是嵌套引起的。

    但因为处于上线紧急的过程中,为了确保,我快速地验证了我的结论:

    1、将子查询的ID单独执行,并把得到的结果序列手动拼成一段ID,如:1,2,3,4, … , 999

    2、将上面得到的序列ID,手动替换到原来的SQL语句

    3、执行,发现,很快!只用了约150 ms

    Well Done! 准备修复上线!

    解决方案

    线上的问题,很多时间都是在定位问题和分析原因,既然问题找到了,原因也找到了,解决方案不言而喻。代码简单处理即可。

    另外一个需要注意的点

    当前,实际的SQL语句,会比这个更为复杂,但已足以表达问题所在。但在前期,笔者也做了一些SQL的代码。

    因为b_table比a_table大,所以一开始 b_table 左关联 a_table 时,很慢,大概是1秒多,而且数据量是很少的;但若反过来,a_table 左关联 b_table 时,则很快,大概是100毫秒。

    所以,又发现一个有趣的现象:

    大表 左关联 小表,很慢;小表 左关联 大表,很快。

    当然,这些我们理论上都知道,但实际开发会忘却。又或者一开始两个表都为空时,而又没考虑到后期这两个表增长的速度时,日后就会埋下坑了。

    总结

    首先,嵌套的子查询是很慢的。

    原因,我还没仔细去研究,但在下班的路上和我的同事交流时,他说曾经看过这方面相关的书籍,是说每一次的子查询都会产生一个SQL语句,所以就N次查询了。而另外一位资深的QA同事则跟我说,应该是M*N的问题。

    其次,我一开始使用嵌套子查询,是存在这样一个误区:我觉得将这些操作交给MySQL自身来处理会更高效,毕竟DB内部会有良好的机制来执行这些查询由。

    然后,实际表白,我错了。因为这不是简单的合并MC批量查询。

    当我们决定使用一些底层的技术时,只有当我们理解透彻了,才能使用更为恰当。而因为无知就断定工具、框架、底层无所不能时,往往就会中招。

    博文出处:http://my.oschina.net/dogstar/blog/398879

    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    正版 Windows 11产品密钥怎么查找/查看?

    还有3个月,微软将停止 Windows 10 的更新

    Windows 10 终止支持后,企业为何要立即升级?

    Windows 10 将于 2025年10 月终止技术支持,建议迁移到 Windows 11

    Windows 12 发布推迟,微软正全力筹备Windows 11 25H2更新

    Linux 退出 mail的命令是什么

    Linux 提醒 No space left on device,但我的空间看起来还有不少空余呢

    hiberfil.sys文件可以删除吗?了解该文件并手把手教你删除C盘的hiberfil.sys文件

    Window 10和 Windows 11哪个好?答案是:看你自己的需求

    盗版软件成公司里的“隐形炸弹”?老板们的“法务噩梦” 有救了!

    IT头条

    公安部:我国在售汽车搭载的“智驾”系统都不具备“自动驾驶”功能

    02:03

    液冷服务器概念股走强,博汇、润泽等液冷概念股票大涨

    01:17

    亚太地区的 AI 驱动型医疗保健:2025 年及以后的下一步是什么?

    16:30

    智能手机市场风云:iPhone领跑销量榜,华为缺席引争议

    15:43

    大数据算法和“老师傅”经验叠加 智慧化收储粮食尽显“科技范”

    15:17

    技术热点

    商业智能成CIO优先关注点 技术落地方显成效(1)

    用linux安装MySQL时产生问题破解

    JAVA中关于Map的九大问题

    windows 7旗舰版无法使用远程登录如何开启telnet服务

    Android View 事件分发机制详解

    MySQL用户变量的用法

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。