• 记一次SQL优化


    业务查询缓慢,要求优化查询速度,优化步骤一一枚举出来,防止忘了。

    总结:

      1、尽量让SQL都使用索引,不要存在in这种不走索引的写法

      2、适当的时候,可以将子查询优化成为表连接

    原SQL:

    SELECT
     tab2.quoteOrderId,
     tab2.quoteOrderNumber,
     tab2.userUpdateTpye,
     tab2.quoteTitle,
     DATE_FORMAT( tab2.quoteClosingDate, '%Y-%m-%d' ) AS quoteClosingDate,
     DATE_FORMAT( tab2.expectedReceivingDate, '%Y-%m-%d' ) AS expectedReceivingDate,
     tab2.totalPrice,
     tab2.quoteDate,
     tab2.user_id AS clientCompany,
     tab2.type 
    FROM
     (
     SELECT
      tab.quoteOrderId,
      tab.quoteOrderNumber,
      tab.userUpdateTpye,
      tab.quoteTitle,
      tab.quoteClosingDate,
      tab.expectedReceivingDate,
      tab.totalPrice,
      tab.quoteDate,
      tab.user_id,
      ( CASE WHEN TAB.countNum = TAB.notApprovedCount THEN 0 WHEN TAB.countNum = adoptCount THEN 2 ELSE 1 END ) AS type 
     FROM
      (
      SELECT
       t1.id AS quoteOrderId,
       t1.quote_order_number AS quoteOrderNumber,
       t1.user_update_tpye AS userUpdateTpye,
       t1.quote_title AS quoteTitle,
       t1.quote_closing_date AS quoteClosingDate,
       t1.expected_receiving_date AS expectedReceivingDate,
       SUM( CASE WHEN t3.approval_status IS NULL THEN 1 ELSE 0 END ) AS notApprovedCount,
       SUM( CASE t3.approval_status WHEN '1' THEN 1 ELSE 0 END ) AS adoptCount,
       SUM( CASE t3.approval_status WHEN '2' THEN 1 ELSE 0 END ) AS refuseCount,
       count( 1 ) countNum,
       SUM(
       t2.amount * IFNULL( t3.bj_unit_price_including_tax, 0 )) AS totalPrice,
       t1.quote_date AS quoteDate,
       t4.user_id 
      FROM
       quote_order_info t1
       LEFT JOIN quote_order_pro_info t2 ON t1.id = t2.quote_order_info_id
       LEFT JOIN quote_bj_order_pro_info t3 ON t3.id IN ( SELECT MAX( id ) FROM quote_bj_order_pro_info WHERE quote_order_pro_info_id = t2.id GROUP BY quote_order_pro_info_id ) 
       AND t3.approval_status = 1
       LEFT JOIN quote_order_user_info t4 ON t4.quote_order_info_id = t1.id 
      GROUP BY
       t1.id,
       t4.user_id 
      ) AS tab 
     ) AS tab2

    简单理解sql,业务sql嵌套较多,拆分sql,分段,感觉外层无法优化,也就是说优化点要集中在内层sql:

    SELECT
       t1.id AS quoteOrderId,
       t1.quote_order_number AS quoteOrderNumber,
       t1.user_update_tpye AS userUpdateTpye,
       t1.quote_title AS quoteTitle,
       t1.quote_closing_date AS quoteClosingDate,
       t1.expected_receiving_date AS expectedReceivingDate,
       SUM( CASE WHEN t3.approval_status IS NULL THEN 1 ELSE 0 END ) AS notApprovedCount,
       SUM( CASE t3.approval_status WHEN '1' THEN 1 ELSE 0 END ) AS adoptCount,
       SUM( CASE t3.approval_status WHEN '2' THEN 1 ELSE 0 END ) AS refuseCount,
       count( 1 ) countNum,
       SUM(
       t2.amount * IFNULL( t3.bj_unit_price_including_tax, 0 )) AS totalPrice,
       t1.quote_date AS quoteDate,
       t4.user_id 
      FROM
       quote_order_info t1
       LEFT JOIN quote_order_pro_info t2 ON t1.id = t2.quote_order_info_id
       LEFT JOIN quote_bj_order_pro_info t3 ON t3.id IN ( SELECT MAX( id ) FROM quote_bj_order_pro_info WHERE quote_order_pro_info_id = t2.id GROUP BY quote_order_pro_info_id ) 
       AND t3.approval_status = 1
       LEFT JOIN quote_order_user_info t4 ON t4.quote_order_info_id = t1.id 
      GROUP BY
       t1.id,
       t4.user_id 

    原sql速率:12.4s

    发现问题1:

     圈出来的这个sql,in可以改为=号, 原因:分组条件是quote_order_pro_info_id ,且quote_order_pro_info_id有限制= t2.id,也就是说这个group by是多此一举,聚合得到的值只有一个

    修正sql后:

    LEFT JOIN quote_bj_order_pro_info t3 ON t3.id = ( SELECT MAX( id ) FROM quote_bj_order_pro_info WHERE quote_order_pro_info_id = t2.id )

    查询速率:0.175s

    优化点2:子查询优化为表连接

    子查询会导致外层查询使用不到索引

    提取步骤:

      提取到与t3同级,也就是与t2同级,使用的t2的条件就应该变为join 的on 条件,因此除了查询出max(id)之外,分组条件 quote_order_pro_info_id 也要查询出来作为连接条件

      t3 的id = 查询列的maxId,则是t3关联t5的关联列在on中体现

    修正后sql:

       left join (SELECT MAX(id) maxId, quote_order_pro_info_id  FROM quote_bj_order_pro_info group by quote_order_pro_info_id) t5 on t5.quote_order_pro_info_id = t2.id
       LEFT JOIN quote_bj_order_pro_info t3 ON t3.id = t5.maxId 
       AND t3.approval_status = 1

    查询速率:0.068s

    欢迎朋友有有趣的案例发表出来一起探讨

      

  • 相关阅读:
    gulp-css-spriter 将css代码中的切片图片合并成雪碧图
    通过JS模拟select表单,达到美化效果[demo]
    jQuery拖拽 & 弹出层
    sublime text 快速编码技巧 GIT图
    原生JS不到30行,实现类似javascript MVC的功能-minTemplate
    javascript拖拽原理与简单实现方法[demo]
    滚动焦点图实现原理和实践[原创视频]
    谈一谈值类型与引用类型和装箱与拆箱
    【原创】asp.net内部原理(三) 第三个版本 (最详细的版本)
    由JS函数返回值引发的一场”血案"
  • 原文地址:https://www.cnblogs.com/aigeileshei/p/14657856.html
Copyright © 2020-2023  润新知