愛在花開的季節 发表于 2024-9-2 09:02:18

【干货实战】SQL太慢,教你调优三板斧-Select篇

文章初衷

我们发现在体系上线初期,SQL运行都是正常的,但是到了业务稳定运行以后,在数据量达到一定水平,我们会发现越来越多的慢SQL出现,严重影响用户体验。
目录
文章初衷
慢SQL的定义
⚠️留意:后两个案例更出色!
【实战】
慢SQL调优---三板斧第一招【由内到外】

慢SQL调优---三板斧第二招【小表驱动大表】
原始SQL
调解次序
慢SQL调优---三板斧第三招【条件前置】
原始SQL
优化后的语句
想知道本篇文章是否对您有帮助,让我有更新下一篇的动力。如果有帮助可以批评“有”,非常感谢各位观众老爷们!

慢SQL的定义

慢SQL,即执行时间较长的SQL查询语句,通常指的是在数据库管理体系中执行时间超过预设阈值的SQL语句。这个阈值可以由数据库管理员根据体系性能和业务需求来设定,常见的阈值可能是2秒、5秒或更长。当一个SQL查询的执行时间超过了这个阈值,它就会被标志为“慢查询”。
慢SQL的存在可能表明数据库性能存在瓶颈,如索引设计不合理、查询逻辑复杂、数据量过大、硬件资源不足等题目。它们会占用更多的CPU、I/O资源,影响数据库的响应速度,低落团体体系性能,乃至导致体系响应耽误或崩溃。
为了优化慢SQL,数据库管理员和开发人员通常必要对其举行详细的分析,包括检察执行筹划、查抄索引使用情况、优化查询语句布局、调解数据库参数等,以提高查询效率和体系性能。别的,定期检察慢查询日志也是发现和解决慢SQL题目标有效本领。
请耐心看完,包管你的优化思路会更加清晰。
⚠️留意:后两个案例更出色!


最后附上《30个业务场景的SQL优化》、《老司机总结的12条 SQL 优化方案》

【实战】

慢SQL调优---三板斧第一招【由内到外】

话不多说,我们进入实战,以下是我们生产环境的一段查询SQL,它运行耗时在157.84秒,那么各人可以想一想,如果是你,看到这一段SQL会怎么入手呢?
原始SQL
SELECT CL.SCRQSTR,
      TEAM.TEAMCODE AS BMID,
      O.BATCHNO,
      O.STYLE_NO,
      O.PO_ID,
      SUM(CL.QTY)AS QTY,
      MX.MXBRS,
      MXBGS.WORK_SEC AS MXGS,
      O.ORDERTYPE,
      O.FACTORY_NAME,
      O.DIC_ORDER_NO,
      O.DIC_ROW_NO,
      O.ORDER_NO FROM
    (SELECT DISTINCT SCRQSTR,
      QTY,
      LSXNO,
      ORDER_NO,
      PROCESSID,
      BID
    FROM T_DG_CLXX
    WHERE CREATE_DATE>='2024-06-21 13:20:00'
            AND CREATE_DATE<'2024-06-21 13:30:00')CL
INNER JOIN T_TEAM_SUSPEND T1
    ON T1.LSXNO=CL.LSXNO
INNER JOIN T_BASIC_TEAM TEAM
    ON TEAM.ID=T1.ID
INNER JOIN T_PRODUCTION_ORDER O
    ON O.ORDER_NO=CL.ORDER_NO
INNER JOIN PROCESS_PATH PATH
    ON PATH.CID=CL.PROCESSID
      AND PATH.PO_ID=O.PO_ID
      AND PATH.WORKID=3
INNER JOIN
    (SELECT COUNT(*)AS MXBRS,
      T.ORDER_NO FROM
      (SELECT DISTINCT USERID,
      ORDER_NO
      FROM T_DG_CLXX
      WHERE CREATE_DATE>='2024-06-21 13:20:00'
                AND CREATE_DATE<'2024-06-21 13:30:00'
                AND LSXNO NOT IN(1,16))T
      GROUP BYT.ORDER_NO)MX
      ON MX.ORDER_NO=CL.ORDER_NO
INNER JOIN
    (SELECT SUM(CASE
      WHEN T.WORK_SEC>600 THEN
      600
      WHEN T.WORK_SEC<10 THEN
      150
      ELSE T.WORK_SEC END)AS WORK_SEC,ORDER_NO FROM
      (SELECT DISTINCT SCRQ,
      WORK_SEC,
      MODULE_ID,
      SEAT_CODE,
      PIECES,
      USERID,
      LSXNO,
      ORDER_NO
      FROM T_DG_CLXX
      WHERE CREATE_DATE>='2024-06-21 13:20:00'
                AND CREATE_DATE<'2024-06-21 13:30:00'
                AND LSXNO NOT IN(1,16))T
      GROUP BYT.ORDER_NO)MXBGS
      ON MXBGS.ORDER_NO=CL.ORDER_NO
GROUP BYCL.SCRQSTR,TEAM.TEAMCODE,O.BATCHNO,O.STYLE_NO,O.PO_ID,MX.MXBRS,MXBGS.WORK_SEC,O.ORDERTYPE,O.FACTORY_NAME,O.DIC_ORDER_NO,O.DIC_ROW_NO,O.ORDER_NO


你是不是也以为很棘手?感觉有业务逻辑,关联了很多表,也有很多子查询。



首先我们可以先对SQL中的子查询举行执行,看是否存在慢SQL,从内到外去剖析。比如以上这段SQL可以单独执行子查询,检察所需耗时。
首先第一个子查询,但是我们不知道这个表有多少数据量,以是我们必要截取前面10条即可,mysql添加条件limit 10,如果是Oracle就是where rownum < 11,执行发现,SQL超过30秒都没有出结果。
SELECT DISTINCT SCRQSTR,
      QTY,
      LSXNO,
      ORDER_NO,
      PROCESSID,
      BID
    FROM T_DG_CLXX
    WHERE CREATE_DATE>='2024-06-21 13:20:00'
            AND CREATE_DATE<'2024-06-21 13:30:00' LIMIT 10; 因此可以判断这个SQL语句异常,可以通过EXPLAIN 来检察是否走索引了,再看一下T_DG_CLXX表有多少数据量。
通过EXPLAIN发现SQL没有走索引,说明CREATE_DATE字段没有建立索引。另外查询发现此表有3700万条数据量,也发现此表会每年举行数据归档,必须保留1年数据。

那么小同伴知道接下来要做什么了吗?

--------------------------------------------------------------------------------------

没错,建立索引!
建立索引以后,查询为0.1秒左右。
然后将原先业务SQL重新执行,查询时间为0.135秒,效率提升1169倍https://i-blog.csdnimg.cn/direct/5ef5597fcd1e41e294f9196753c1c408.png

这个案例很简朴,CREATE_DATE字段由于是后面业务必要,属于新增的字段。增长字段忘记增长索引,后面出现题目过一次,但是研发又忘记添加索引了,后面我们运维团队通过慢SQL预警发现了这条SQL异常。

慢SQL调优---三板斧第二招【小表驱动大表】

前面谁人案例是不是很简朴,下面这个看到调优结果也会以为很简朴,但是很经典。
给我一个支点,我能翘起整个
页: [1]
查看完整版本: 【干货实战】SQL太慢,教你调优三板斧-Select篇