sql的cout()统计数据太多不知道有没有办法提高查询速度


select a.code as reportCode,b.id,f.NAME,b.title,b.CODE,to_char(b.START_DATE,'yyyy') as year,b.RGID,c.TITLE as groupName,count(e.VALUE) as dataNum
        from T_R_MT_UREPORT a
        right join (select * from T_R_MONITOR_TASK where is_del=0) b on a.mtid=b.id
        left outer join (select * from T_R_MT_REPORT_GROUP where IS_DEL=0) c on b.RGID=c.ID
        left outer join (select * from T_R_MT_RG_ITEM where IS_DEL=0 and TITLE in ('检测项目')) d on c.ID=d.RGID
        left outer join (select * from T_R_MT_REPORT_DATA where IS_DEL=0) e on d.ID=e.RGIID and b.ID=e.MTID
        left outer join (select * from T_B_ORGANIZATION where IS_DEL=0) f on b.OID=f.ID
        where
        a.IS_DEL=0
        and b.VALID_STAGE >= 6
        and c.IS_SUBMIT=1
        and f.VALID_STAGE IN (8,9)
        and e.CODE IN (
        SELECT y.CODE FROM T_R_MT_RG_ITEM z
        LEFT OUTER JOIN T_R_MT_REPORT_DATA y ON z.ID=y.RGIID
        WHERE z.RGID=c.ID AND z.TITLE IN ('报告编号') AND y.VALUE = a.code and y.mtid=b.id
        )
        group by a.code,f.NAME,b.id,b.TITLE,b.CODE,to_char(b.START_DATE,'yyyy'),b.RGID,c.TITLE
        having count(e.VALUE) > 0
        order by dataNum desc

这个代码是你自己写的?干嘛要用这么多的子查询呢,我这里经常交互访问的元组创建了索引,你可以用exist代替in,效率更高很多,这些还得结合你具体的执行计划来看,有的时候不是光改代码逻辑就看得到明显性能提升


CREATE INDEX idx_T_R_MT_UREPORT_IS_DEL ON T_R_MT_UREPORT (IS_DEL);
CREATE INDEX idx_T_R_MONITOR_TASK_is_del ON T_R_MONITOR_TASK (is_del);
CREATE INDEX idx_T_R_MONITOR_TASK_VALID_STAGE ON T_R_MONITOR_TASK (VALID_STAGE);
CREATE INDEX idx_T_R_MT_REPORT_GROUP_IS_DEL ON T_R_MT_REPORT_GROUP (IS_DEL);
CREATE INDEX idx_T_R_MT_RG_ITEM_IS_DEL ON T_R_MT_RG_ITEM (IS_DEL);
CREATE INDEX idx_T_R_MT_RG_ITEM_TITLE ON T_R_MT_RG_ITEM (TITLE);
CREATE INDEX idx_T_R_MT_REPORT_DATA_IS_DEL ON T_R_MT_REPORT_DATA (IS_DEL);
CREATE INDEX idx_T_B_ORGANIZATION_IS_DEL ON T_B_ORGANIZATION (IS_DEL);
CREATE INDEX idx_T_B_ORGANIZATION_VALID_STAGE ON T_B_ORGANIZATION (VALID_STAGE);

CREATE INDEX idx_T_R_MONITOR_TASK_id_VALID_STAGE ON T_R_MONITOR_TASK (id, VALID_STAGE);
CREATE INDEX idx_T_R_MT_REPORT_GROUP_ID_IS_SUBMIT ON T_R_MT_REPORT_GROUP (ID, IS_SUBMIT);
CREATE INDEX idx_T_R_MT_RG_ITEM_RGID_TITLE_ID ON T_R_MT_RG_ITEM (RGID, TITLE, ID);
CREATE INDEX idx_T_R_MT_REPORT_DATA_RGIID_MTID ON T_R_MT_REPORT_DATA (RGIID, MTID);

CREATE INDEX idx_T_R_MT_UREPORT_code ON T_R_MT_UREPORT (code);
CREATE INDEX idx_T_R_MONITOR_TASK_id_title_START_DATE_RGID_CODE ON T_R_MONITOR_TASK (id, title, START_DATE, RGID, CODE);
CREATE INDEX idx_T_R_MT_REPORT_GROUP_ID_TITLE ON T_R_MT_REPORT_GROUP (ID, TITLE);
CREATE INDEX idx_T_B_ORGANIZATION_NAME ON T_B_ORGANIZATION (NAME);

问题点:查询数据较多,提高查询效率
分析思路:一般提高查询效率的方法,
①建立常用的索引(推荐)立竿见晓的提升
②查询语句优化,尽量减少跨表的join操作,大表join小表,搞不好就是扫描全表,这种情况,还是试试建立一个临时表,在临时表的基础上进行查询.
③数据库表结构优化,这个类似②的操作,就是改动的动作更大.

可以参考一下


SELECT
    a.code AS reportCode,
    b.id,
    f.NAME,
    b.title,
    b.CODE,
    TO_CHAR(b.START_DATE, 'yyyy') AS year,
    b.RGID,
    c.TITLE AS groupName,
    COUNT(e.VALUE) AS dataNum
FROM
    T_R_MT_UREPORT a
    JOIN T_R_MONITOR_TASK b ON a.mtid = b.id AND b.is_del = 0
    LEFT JOIN T_R_MT_REPORT_GROUP c ON b.RGID = c.ID AND c.IS_DEL = 0
    LEFT JOIN T_R_MT_RG_ITEM d ON c.ID = d.RGID AND d.IS_DEL = 0 AND d.TITLE = '检测项目'
    LEFT JOIN T_R_MT_REPORT_DATA e ON d.ID = e.RGIID AND b.ID = e.MTID AND e.IS_DEL = 0
    LEFT JOIN T_B_ORGANIZATION f ON b.OID = f.ID AND f.IS_DEL = 0
WHERE
    a.IS_DEL = 0
    AND b.VALID_STAGE >= 6
    AND c.IS_SUBMIT = 1
    AND f.VALID_STAGE IN (8, 9)
    AND EXISTS (
        SELECT 1
        FROM
            T_R_MT_RG_ITEM z
            LEFT JOIN T_R_MT_REPORT_DATA y ON z.ID = y.RGIID AND y.IS_DEL = 0
        WHERE
            z.RGID = c.ID
            AND z.TITLE = '报告编号'
            AND y.VALUE = a.code
            AND y.mtid = b.id
    )
GROUP BY
    a.code,
    f.NAME,
    b.id,
    b.TITLE,
    b.CODE,
    TO_CHAR(b.START_DATE, 'yyyy'),
    b.RGID,
    c.TITLE
HAVING
    COUNT(e.VALUE) > 0
ORDER BY
    dataNum DESC;

哥们,你得先把你的sql拆解一下,我先说下我的思路哈
1.把多次嵌套查询的sql单独执行,检查执行结果。如:SELECT * FROMT_R_MT_RG_ITEM WHERE IS_DEL = 0 AND TITLE IN ( '检测项目', SELECT * FROM T_R_MT_REPORT_DATA WHERE IS_DEL = 0,SELECT * FROM T_B_ORGANIZATION WHERE IS_DEL = 0 )等,这种sql如果执行慢,那后续肯定慢,没得跑
2.在确定这几个sql执行都没问题的情况下,检查是否执行索引,这个可以在navicat中查看

img


这个查询可以通过navicat的解释已选择按钮达到,选择执行的sql,然后点击如下按钮即可

img

不知道你这个问题是否已经解决, 如果还没有解决的话:

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^

首先你的子查询太多了,优化下,explain看下你这条sql的执行计划,其次就是如果联查的话加上索引

img

img

看下有没有办法减少left join的次数,然后left join的关联字段添加索引,where后面的字段增加索引试试。

你这sql复杂度不高,我把你每个selec * 里的条件加到where里去,这样全量查询一次,你试试

select a.code as reportCode,b.id,f.NAME,b.title,b.CODE,to_char(b.START_DATE,'yyyy') as year,b.RGID,c.TITLE as groupName,count(e.VALUE) as dataNum
        from T_R_MT_UREPORT a
        right join T_R_MONITOR_TASK b on a.mtid=b.id
        left outer join T_R_MT_REPORT_GROUP  c on b.RGID=c.ID
        left outer join T_R_MT_RG_ITEM   d on c.ID=d.RGID
        left outer join T_R_MT_REPORT_DATA e on d.ID=e.RGIID and b.ID=e.MTID
        left outer join T_B_ORGANIZATION  f on b.OID=f.ID
        where
        a.IS_DEL=0 and  b.IS_DEL=0 and c.IS_DEL=0 
        and d.IS_DEL=0 and TITLE in ('检测项目') and e.IS_DEL=0
        and f.IS_DEL=0
        and b.VALID_STAGE >= 6
        and c.IS_SUBMIT=1
        and f.VALID_STAGE IN (8,9)
        and e.CODE IN (
        SELECT y.CODE FROM T_R_MT_RG_ITEM z
        LEFT OUTER JOIN T_R_MT_REPORT_DATA y ON z.ID=y.RGIID
        WHERE z.RGID=c.ID AND z.TITLE IN ('报告编号') AND y.VALUE = a.code and y.mtid=b.id
        )
        group by a.code,f.NAME,b.id,b.TITLE,b.CODE,to_char(b.START_DATE,'yyyy'),b.RGID,c.TITLE
        having count(e.VALUE) > 0
        order by dataNum desc

你的查询有很多连接查询,可能需要考虑重新规划下你的查询语句。前面说的建立索引,效果应该不大。还是应该从sql语句下手。不必统计所有数据,可以使用LIMIT和OFFSET子句来分页查询。通过限制返回的行数,可以减少查询的数据量。如果表非常大,可以考虑使用数据库分区来将表分成较小的部分。每个分区可以单独查询,从而提高查询性能。

创建索引可以提高速度

建索引

帮你优化了一下 有帮助的话 采纳一下


SELECT
  a.code AS reportCode,
  b.id,
  f.NAME,
  b.title,
  b.CODE,
  b.START_DATE AS year,  
  b.RGID,
  c.TITLE AS groupName,
  COUNT(e.VALUE) AS dataNum
FROM T_R_MT_UREPORT a
LEFT JOIN T_R_MONITOR_TASK b ON a.mtid = b.id 
LEFT JOIN T_R_MT_REPORT_GROUP c ON b.RGID = c.ID
LEFT JOIN T_R_MT_RG_ITEM d ON c.ID = d.RGID
LEFT JOIN T_R_MT_REPORT_DATA e ON d.ID = e.RGIID AND b.ID = e.MTID  
LEFT JOIN T_B_ORGANIZATION f ON b.OID = f.ID
WHERE
  a.IS_DEL = 0
  AND b.VALID_STAGE >= 6
  AND c.IS_SUBMIT = 1
  AND f.VALID_STAGE IN (8,9) 
  AND e.CODE IN (
    SELECT y.CODE 
    FROM T_R_MT_RG_ITEM z
    LEFT JOIN T_R_MT_REPORT_DATA y ON z.ID = y.RGIID 
    WHERE z.RGID = c.ID AND z.TITLE IN ('报告编号') AND y.VALUE = a.code and y.mtid = b.id
  )
GROUP BY 
  a.code, b.id, f.NAME, b.title, b.CODE, b.START_DATE, b.RGID, c.TITLE
HAVING
  COUNT(e.VALUE) > 0
ORDER BY
  dataNum DESC

参考newbing
当 SQL 查询的结果集过大时,可以尝试以下几种方法来提高查询速度:

  1. 索引优化:确保相关列上有适当的索引。通过创建索引,可以加快查询的速度。你可以在经常用于过滤、连接或排序的列上创建索引。在这个查询中,你可以考虑在 T_R_MONITOR_TASK 表的 is_del 列上创建索引,以及在 T_R_MT_REPORT_GROUP 表的 IS_DEL 列上创建索引。

  2. 子查询优化:尽量减少子查询的使用。子查询在某些情况下可能会导致性能下降。你可以尝试将子查询转换为连接或其他更高效的方式来处理。

  3. 数据库优化:确保数据库的配置和参数设置合理。例如,你可以调整数据库的缓冲区大小、并发连接数等参数,以提高查询性能。

  4. 数据库分区:如果数据量非常大,你可以考虑对表进行分区。分区可以将表的数据划分为多个逻辑部分,并将其存储在不同的物理位置上,从而提高查询性能。

  5. 数据库缓存:使用适当的缓存机制来减少对数据库的访问次数。例如,你可以使用缓存来存储频繁查询的结果,以减少对数据库的查询操作。

  6. 数据库性能监控:定期监控数据库的性能,并识别潜在的性能瓶颈。通过监控和优化数据库的性能,可以提高查询的速度。

请注意,以上方法可能需要根据你的具体情况进行调整和实施。如果你不确定如何进行优化,建议咨询数据库管理员或专业人士的帮助。