美文网首页
一次Sql优化的体验

一次Sql优化的体验

作者: AmosZhu | 来源:发表于2019-09-19 19:27 被阅读0次

今天遇到一个SQL优化的问题,记录下来

测试部门反映,有个功能的查询很缓慢,需要支持排查下

首先描述下具体的问题

数据库中一张表的大概有700多条记录,业务需要模拟一个类似属性树形的数据结构,需要查询所有父类的列表数据,查询出来符合记录的大概有400多条,目前测试点击查询,所需要的时间大概在4s多,这个效率实在太慢了;

下面是SQL的内容

    SELECT
      (SELECT
        MAX(f.url)
      FROM
        order_definnition o
         JOIN order_def_form_relation d
          ON o.id = d.pid
          AND d.is_interflow = 1
          AND o.is_deleted = 0
          AND d.is_deleted = 0
         JOIN form f
          ON f.id = d.form_id
          AND f.is_deleted = 0
      WHERE o.resource_code = t.from_oddf_class_no) AS url,
      (SELECT
        MAX(f.url)
      FROM
        order_definnition o
         JOIN order_def_form_relation d
          ON o.id = d.pid
          AND d.is_audit = 1
          AND o.is_deleted = 0
          AND d.is_deleted = 0
         JOIN form f
          ON f.id = d.form_id
          AND f.is_deleted = 0
      WHERE o.resource_code = t.from_oddf_class_no) AS source_url,
      id
    FROM
      unicom_send_recv_order t
    WHERE is_deleted = 0
      AND t.id IN
      (SELECT
        (SELECT
          b.id
        FROM
          unicom_send_recv_order b
        WHERE b.is_deleted = 0
          AND b.unicom_first_id = a.unicom_first_id
          AND (
            b.data_direction = 0
            OR (
              b.data_direction = 1
              AND (
                b.order_status = '1001516'
                OR b.order_status = '1001515'
              )
            )
            OR b.is_start_line = 1
          )
        ORDER BY b.send_recv_count DESC
        LIMIT 1)
      FROM
        unicom_send_recv_order a
      WHERE a.is_deleted = 0
      GROUP BY a.unicom_first_id)
    ORDER BY t.created_time DESC

这个sql的逻辑,在满足一定的条件下,选择send_recv_count最大的那条记录的id来展示。

添加索引

在不影响业务的条件下,我们通过添加索引来试试,查看表中的关联字段,我们需要对如下的字段添加索引

    ALTER TABLE `sceo`.`unicom_send_recv_order`   
      ADD  INDEX `index_unicom_first_id` (`unicom_first_id`),
      ADD  INDEX `index_from_oddf_class_no` (`from_oddf_class_no`),
      ADD  INDEX `index_send_recv_count` (`send_recv_count`);
    ALTER TABLE `sceo`.`order_def_form_relation`   
      ADD  INDEX `index_pid` (`pid`),
      ADD  INDEX `index_form_id` (`form_id`);

再次执行该上面的sql语句,发现查询的效率变快了了,耗时2700+ms数,这个时间还是满足不了业务的需要

重构sql

分析上述的sql,发现在子查询中通过排序来获取send_recv_count最大的记录,然后再分组查询,这个是主要导致查询效率缓慢的原因,我们可以改写sql语句来减少分组和排序

我们利用变量来为排序标记,然后获取变量为1的记录,利用这种方式来避免排序分组, 重构的sql如下:

    SELECT
      (SELECT
        MAX(f.url)
      FROM
        order_definnition o
         JOIN order_def_form_relation d
          ON o.id = d.pid
          AND d.is_interflow = 1
          AND o.is_deleted = 0
          AND d.is_deleted = 0
         JOIN form f
          ON f.id = d.form_id
          AND f.is_deleted = 0
      WHERE o.resource_code = t.from_oddf_class_no) AS url,
      (SELECT
        MAX(f.url)
      FROM
        order_definnition o
         JOIN order_def_form_relation d
          ON o.id = d.pid
          AND d.is_audit = 1
          AND o.is_deleted = 0
          AND d.is_deleted = 0
         JOIN form f
          ON f.id = d.form_id
          AND f.is_deleted = 0
      WHERE o.resource_code = t.from_oddf_class_no) AS source_url, id
    FROM
      unicom_send_recv_order t
    WHERE is_deleted = 0
       AND EXISTS
      (SELECT tt.id from (SELECT
        b.id,
        b.unicom_first_id,
        send_recv_count,
    IF (
        @pre_course_id = b.unicom_first_id,
        @cur_rank := @cur_rank + 1,
        @cur_rank := 1
    ) ranking,
     @pre_course_id := b.unicom_first_id
    FROM
        unicom_send_recv_order b,
        (SELECT
                @cur_rank := 0,
                @pre_course_id := NULL
        ) r
    where b.is_deleted = 0 
          AND (b.data_direction = 0
           OR (b.data_direction = 1
              AND (b.order_status = '1001516'
                OR b.order_status = '1001515'))
            OR b.is_start_line = 1)
    ORDER BY
        unicom_first_id,
        send_recv_count DESC) tt where tt.ranking = 1
        AND tt.id = t.id)
    ORDER BY t.created_time DESC

在重构后的sql中,可以看到我们排序之后的记录添加一个序列,然后获取序列的第一条来作为我们现实的记录,然后将in改为exists,这样优化后的查询就变得效率很高了,经过测试,耗时降到了200ms,这个速度暂时是可以接受的了

相关文章

  • SQL优化分享

    SQL优化分享 最近公司部门内部进行了一次分享,是总工给我们进行的一次关于SQL优化的内容。相信关于SQL的优化也...

  • 一次Sql优化的体验

    今天遇到一个SQL优化的问题,记录下来 测试部门反映,有个功能的查询很缓慢,需要支持排查下 首先描述下具体的问题 ...

  • 常用sql优化2019-09-27

    sql优化 sql优化.................................................

  • mysql数据库优化

    1. Mysql优化介绍 1.1 sql优化 a. sql优化分析b. 索引优化c. 常用sql优化d. 常用优化...

  • Mysql 优化

    1.Sql优化 1)sql优化分析2)索引优化3)sql语句优化4)一些常用的技巧优化 (正则、函数) 2.优化数...

  • sql优化的一般策略

    sql 优化的一般策略:索引优化,sql改写,参数优化,优化器 索引优化 以select * from vvsho...

  • SQL语句优化, since 2022-04-22

    (2022.04.22 Fri)SQL语句的优化目的在于提高SQL语句的运行效率。注意SQL优化和数据库优化的区别...

  • MySQl优化学习笔记(七)SQL优化简介

    一、SQL优化简介 1、我们平时说的SQL优化就是优化SQl语句和索引(通俗说就是使用什么样的SQL语句能够让索引...

  • 11-mysqlSQL分析

    六星教育 - java-mysql优化1909 SQL优化 所谓SQL优化:基于MySQL的优化器查询规则来优化S...

  • sql的一些优化建议

    sql的索引设计和表优化都是非常重要的点,好的sql可以极大的减低成本,提高用户体验,而一条不好的sql就有可能让...

网友评论

      本文标题:一次Sql优化的体验

      本文链接:https://www.haomeiwen.com/subject/oagructx.html