【问题标题】:Optimizing query in MySQL- joins and subqueries?优化 MySQL 中的查询 - 连接和子查询?
【发布时间】:2015-05-19 15:20:06
【问题描述】:

我有几个表格:一个用户表格,以及记录他们可以执行的各种操作(即下载、阅读、测验等)的表格。我正在尝试生成一个表格,列出每个用户,以及他们迄今为止采取的行动数量。

SELECT a.user_id, b.action1 + c.action2 + d.action3 AS actions
FROM table_of_applicable_users a
LEFT JOIN 
    (SELECT DISTINCT e.user_id , COUNT( e.user_id ) AS action1
    FROM table_of_actions1 e
    JOIN user_records f ON f.user_id = e.user_id
    WHERE f.group_id =15
    GROUP BY e.user_id )b
LEFT JOIN 
    (SELECT DISTINCT g.user_id , COUNT( g.user_id ) AS action2
    FROM table_of_actions2 g
    JOIN user_records h ON h.user_id = g.user_id
    WHERE h.company_id =15
    GROUP BY g.user_id )c
LEFT JOIN 
    (SELECT DISTINCT i.user_id , COUNT( i.user_id ) AS action3
    FROM table_of_actions3 i
    JOIN user_records j ON j.user_id = i.user_id
    WHERE j.company_id =15
    GROUP BY user_id )d
JOIN user_records z ON z.user_id = a.user_id
WHERE z.group_id =15
GROUP BY a.user_id

我在每个子查询中加入用户记录表,因为我发现它减少了大约一半的行数。但是,查询仍然需要太多时间。我该如何进一步优化这个查询,或者创建一个返回相似结果的新查询?

附言结果的所需格式如下:

user_id    number of actions
00001      459
00002      2461, etc.

【问题讨论】:

  • 你在 mysql 和 sql server 中有这个表和查询吗?
  • 你只能说,你为什么要使用 distinct。此外还有不必要的连接使用。你确定上面的查询正在运行并给出正确的输出吗?因为在每个左连接之后缺少 on 子句。如果 t'row 还有一个动作,你会再创建一个表等等。
  • 你使用的是什么数据库,MySQL 还是 SQL Server?
  • 除非你有最新版本的 MySQL,否则JOINing 多个子查询是非常低效的。这是因为子查询没有索引。 5.6.7 增加了这样的。你运行的是什么版本? (也就是说,升级可能会有所帮助,或者有其他原因导致性能不佳。)
  • 这是在运行版本 5.6.16-log 的 MySQL 服务器上。我尝试了 Rick James 的方法,最大组的时间缩短到了 44 秒,这比以前有了很大的改进。我将尽快尝试其他解决方案并标记最佳解决方案。谢谢大家的帮助。

标签: mysql sql-server join optimization subquery


【解决方案1】:

KumarHarsh 很接近。但需要进行一些修复:

Select user_id, SUM(actions) AS actions from  -- Note: SUM
(
( SELECT  e.user_id , COUNT(*) AS actions
    FROM table_of_actions1 e
    JOIN user_records f ON f.user_id = e.user_id
    WHERE f.group_id = 15
    GROUP BY e.user_id )
UNION ALL
( SELECT  g.user_id , COUNT(*) AS actions
    FROM table_of_actions2 g
    JOIN user_records h ON h.user_id = g.user_id
    WHERE h.company_id = 15
    GROUP BY g.user_id )
UNION ALL
( SELECT  i.user_id ,  COUNT(*) AS actions
    FROM table_of_actions2 j
    JOIN user_records j ON j.user_id = i.user_id
    WHERE j.company_id = 15
    GROUP BY user_id )
) t4
)
GROUP BY user_id;   -- Note: GROUP BY

但是!...由于JOINGROUP BY 可能会为COUNT 提供过高的值。建议您检查一下,看看它是否得到了正确的计数,或者一些夸大的值:

SELECT e.user_id , COUNT(*) AS action1
    FROM table_of_actions1 e
    JOIN user_records f ON f.user_id = e.user_id
    WHERE f.group_id = 15
    GROUP BY e.user_id;

如果它被夸大了,那么我们将不得不更加努力地使您的查询快速正确。

【讨论】:

    【解决方案2】:

    我正在尝试了解您的要求, 我从查询中删除的东西我发现是不必要的。

    Select user_id,action1+action2+action3 AS actions from
    (
    SELECT  e.user_id , COUNT( e.user_id ) AS action1
        FROM table_of_actions1 e
        JOIN user_records f ON f.user_id = e.user_id
        WHERE f.group_id =15
        GROUP BY e.user_id
    
    union all
    
    SELECT  g.user_id , COUNT( g.user_id ) AS action2
        FROM table_of_actions2 g
        JOIN user_records h ON h.user_id = g.user_id
        WHERE h.company_id =15
        GROUP BY g.user_id 
    
    union all
    SELECT  i.user_id , COUNT( i.user_id ) AS action3
        FROM table_of_actions3 i
        JOIN user_records j ON j.user_id = i.user_id
        WHERE j.company_id =15
        GROUP BY user_id
    )t4
    

    【讨论】:

      【解决方案3】:

      table_of_actions1、table_of_actions2、table_of_actions3 和 user_records 中的 userid 列是否被索引?尝试以下语句一次

      SELECT a.user_id, b.action1 + c.action2 + d.action3 AS actions FROM table_of_applicable_users a LEFT JOIN (SELECT DISTINCT e.user_id , COUNT( e.user_id ) AS action1 FROM table_of_actions1 e JOIN (SELECT user_id, group_id from user_records where group_id = 15) f ON f.user_id = e.user_id WHERE f.group_id =15 GROUP BY e.user_id )b LEFT JOIN (SELECT DISTINCT g.user_id , COUNT( g.user_id ) AS action2 FROM table_of_actions2 g JOIN (SELECT user_id, company_id from user_records where company_id= 15) h ON h.user_id = g.user_id WHERE h.company_id =15 GROUP BY g.user_id )c LEFT JOIN (SELECT DISTINCT i.user_id , COUNT( i.user_id ) AS action3 FROM table_of_actions3 i JOIN (SELECT user_id, company_id from user_records where company_id = 15) j ON j.user_id = i.user_id WHERE j.company_id =15 GROUP BY user_id )d JOIN user_records z ON z.user_id = a.user_id WHERE z.group_id =15 GROUP BY a.user_id

      【讨论】:

        猜你喜欢
        • 2020-05-10
        • 1970-01-01
        • 1970-01-01
        • 2010-11-06
        • 2023-01-03
        • 2020-02-14
        • 1970-01-01
        • 2017-04-04
        • 2020-01-02
        相关资源
        最近更新 更多