SQL优化方案

车辆综合查询报表接口优化

背景:

通过日志平台对车辆综合查询接口的响应时间进行分析,发现当前接口的平均响应时间比较长,为了提高用户使用的体验,需要对接口进行优化

image-20250326100631247

目的:

  1. 整理用户权限和组织权限之间的区别和涉及到的表信息
  2. 基础节点信息的表改造,添加排序字段,优化查询速度
  3. 相关接口:
    • /car/queryMonitorList
    • /optimize/queryFuelCarList

对接口调用链路分析:

image-20250326100858859

分析发现,主要还是SQL层面的响应时间比较长,所以从SQL进行优化

流程:

  • 首先调用车辆综合报表方法xxQueryFuelCarList

  • 进入查询车辆车次计数xxCarAllCount

  • 遍历车辆节点表xx_Node_CarInFo_Car找到对应节点

  • 对应节点车辆的基础信息表xx_Node_relationship

    基础节点SQL

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    -- 执行查询,查找根节点及其所有后代节点
    SELECT id, name
    FROM (
    SELECT t1.id,
    t1.pid,
    IF(FIND_IN_SET(t1.pid, @pids) > 0, @pids := CONCAT(@pids, ',', t1.id), 0) AS ischild,
    t1.name
    FROM (
    SELECT id, pid, name
    FROM rl_organize_link_relation
    WHERE del = 0
    ORDER BY pid, id
    ) AS t1
    ) AS da
    WHERE ischild != 0 OR id = 1;

    主要瓶颈

    FIND_IN_SET查询@pids中是否有t1.pid的结果,基础节点表被很多表关联查询,查询时需要对每个节点进行遍历,在数据量多的情况下效率低, 多表级联查询慢问题

优化方案:

  • 优化SQL查询:减少多表级联查询.sql拆分优化
  • 数据库索引优化:对应索引是否命中,索引优化
  • 表设计优化:增加组织节点排序字段舍弃递归查询,直接查询已经是排好序的数据结构;
  • kudu优化:位置云查询动态数据的性能优化

首先从SQL结构进行优化:

对SQL进行分析,得出结论需要对IF(find_in_set(pid, @pids)函数进行改造

思路:添加一个排序字段,将节点进行分层,减少每次查询所扫描的节点数量,观察优化后的查询时间再考虑其他方案

具体执行如下:

SQL优化(提升82%):

  • 优化前-查询记录28471条,查询时间8.617s

    image-20250305180619797

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    SELECT id, name
    FROM (
    SELECT t1.id,
    pid,
    IF(find_in_set(pid, @pids) > 0, @pids := concat(@pids, ',',id), 0) AS ischild,
    `name`
    FROM (SELECT id, pid, `name`
    FROM rl_organize_link_relation
    AS t
    WHERE t.del = 0
    ORDER BY pid, id) AS t1,
    (SELECT @pids := 1) AS t2) AS da
    WHERE ischild != 0 OR id = 1;
  • 优化后-查询记录28471条,查询时间1.549s

    image-20250305180839257

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    SELECT id, name, pid AS parent_id
    FROM (
    SELECT id, pid, name
    FROM rl_organize_link_relation
    WHERE del = 0
    ORDER BY pid, id
    ) AS sorted,
    (SELECT @pv := #{id}) AS init
    WHERE FIND_IN_SET(pid, @pv)
    AND LENGTH(@pv := CONCAT(@pv, ',', id))
    UNION ALL
    -- 加上起始节点(根节点)
    SELECT id, name, pid AS parent_id
    FROM rl_organize_link_relation
    WHERE id = #{id};

接口提升时间:

优化后的基础节点SQL提升较大,我们再看看接口的提升效果

优化前:

image-20250326102447896接口的响应时间在30s+上下

优化后:

image-20250326103322279

接口的响应时间在15s+上下,提升50%+