繁体   English   中英

我想优化 SQL 查询,因为它花了太多时间

[英]I want to optimize the SQL query because it took too much time

我有这个 SQL 查询的问题。 我想获得每个角色创建的“ops”的数量。

例如 :

| Projects | oprs count (role A) |    oprs count (role B)      |
|----------|---------------------|-----------------------------|
| Project1 |     100             |             10              |
| Project2 |     10              |             20              |
| Project3 |     80              |             30              |

在此处输入图片说明

我已经完成了这个查询,但它很慢,因为“oprs”表很大,你能帮我把它做得更好吗?

 EXPLAIN SELECT DISTINCT
    pr.id 'project ID',
    pr.name 'project',
    (SELECT 
            COUNT(DISTINCT o.id)
        FROM
            oprs o
                LEFT JOIN
            accounts ac ON ac.id = o.create_account_id AND NOT(ac.is_deleted)
                LEFT JOIN
            users u ON u.account_id = ac.id AND NOT(u.is_deleted)
                LEFT JOIN
            links_users_roles lur ON lur.user_id = u.id AND NOT(lur.is_deleted)
                LEFT JOIN
            roles r ON r.id = lur.role_id
        WHERE
            o.project_id = pr.id
            AND r.id = 31
    )AS 'count oprs created with role A',
    (SELECT 
            COUNT(DISTINCT o.id)
        FROM
            oprs o
                LEFT JOIN
            accounts ac ON ac.id = o.create_account_id AND NOT(ac.is_deleted)
                LEFT JOIN
            users u ON u.account_id = ac.id AND NOT(u.is_deleted)
                LEFT JOIN
            links_users_roles lur ON lur.user_id = u.id AND NOT(lur.is_deleted)
                LEFT JOIN
            roles r ON r.id = lur.role_id
        WHERE
            o.project_id = pr.id
            AND r.id = 252
    )AS 'count oprs created with role B'
FROM
    projets pr
GROUP BY pr.id

这是查询的解释:

在此处输入图片说明

先感谢您

我首先将查询编写为单个聚合查询。 我不知道这是否会更快——但可能会。 它绝对更简单:

SELECT pr.id, pr.name,
       COUNT(DISTINCT CASE WHEN lur.role_id = 31 THEN o.id END),
       COUNT(DISTINCT CASE WHEN lur.role_id = 252 THEN o.id END)
FROM projects pr LEFT JOIN
     oprs o
     ON o.project_id = pr.id LEFT JOIN
     accounts ac
     ON ac.id = o.create_account_id AND
        NOT(ac.is_deleted) LEFT JOIN
     users u
     ON u.account_id = ac.id AND
        NOT(u.is_deleted) LEFT JOIN
     links_users_roles lur
     ON lur.user_id = u.id AND
         NOT(lur.is_deleted)
GROUP BY pr.id, pr.name;

请注意,“缺少”一张表。 不需要它,因为角色 ID 在links_users_roles

接下来,我会质疑是否需要COUNT(DISTINCT) 它增加了开销。 如果不是真的有必要,我不会感到惊讶。 这也会加快查询速度。

正如 Gordon Linoff 解释的那样,您可以重构代码以使其更易于阅读。 我想补充一点,您有多种方法可以改进这一点。 首先,您可以实现一个定期加载此查询并保存结果的 cron 作业,因此当需要数据时,只会查询结果,而不是一次又一次地计算冗长的过程。 接下来,您可能希望索引一些字段,例如外键,例如project_id ,这将提高查询的性能。 但是,它会稍微降低保存记录的性能。

从戈登离开的地方开始……

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM