关闭 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

    上一篇返回首页 下一篇

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

    别人在看

    抖音安全与信任开放日:揭秘推荐算法,告别单一标签依赖

    ultraedit编辑器打开文件时,总是提示是否转换为DOS格式,如何关闭?

    Cornell大神Kleinberg的经典教材《算法设计》是最好入门的算法教材

    从 Microsoft 下载中心安装 Windows 7 SP1 和 Windows Server 2008 R2 SP1 之前要执行的步骤

    Llama 2基于UCloud UK8S的创新应用

    火山引擎DataTester:如何使用A/B测试优化全域营销效果

    腾讯云、移动云继阿里云降价后宣布大幅度降价

    字节跳动数据平台论文被ICDE2023国际顶会收录,将通过火山引擎开放相关成果

    这个话题被围观超10000次,火山引擎VeDI如此解答

    误删库怎么办?火山引擎DataLeap“3招”守护数据安全

    IT头条

    平替CUDA!摩尔线程发布MUSA 4性能分析工具

    00:43

    三起案件揭开侵犯个人信息犯罪的黑灰产业链

    13:59

    百度三年开放2.1万实习岗,全力培育AI领域未来领袖

    00:36

    工信部:一季度,电信业务总量同比增长7.7%,业务收入累计完成4469亿元

    23:42

    Gartner:2024年全球半导体营收6559亿美元,AI助力英伟达首登榜首

    18:04

    技术热点

    iOS 8 中如何集成 Touch ID 功能

    windows7系统中鼠标滑轮键(中键)的快捷应用

    MySQL数据库的23个特别注意的安全事项

    Kruskal 最小生成树算法

    Ubuntu 14.10上安装新的字体图文教程

    Ubuntu14更新后无法进入系统卡在光标界面解怎么办?

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

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