【问题标题】:How to optimize sql query with COUNT and GROUP BY如何使用 COUNT 和 GROUP BY 优化 sql 查询
【发布时间】:2017-10-08 02:13:02
【问题描述】:

我有一个表 cast 大约有 150 万行,还有一个较小的表 watched 大约有 1000-2000 行。两个表共享一个名为movieId 的列。我正在尝试运行此查询:

SELECT actorId, COUNT( actorId )
FROM cast t1
WHERE EXISTS (    
    SELECT userId
    FROM watched t2
    WHERE t1.movieId = t2.movieId
    AND t2.userId =8
)
GROUP BY actorId

但是,返回结果大约需要 5 秒。我是 cast 表中 actorId 和 movieId 的多列索引,以及 watched 表中 userId 和 movieId 的索引。 该查询返回大约 20000 个结果。 有什么方法可以优化我的查询/表,以便查询运行得更快?

【问题讨论】:

    标签: mysql sql group-by exists


    【解决方案1】:

    对于这个查询:

    SELECT c.actorId, COUNT(*)
    FROM cast c
    WHERE EXISTS (SELECT 1
                  FROM watched w
                  WHERE w.movieId = c.movieId AND w.userId = 8
                 )
    GROUP BY c.actorId;
    

    您希望在watched(movieId, userId) 上建立索引。 cast(movieId, actorId) 上的索引也可能很有用。

    请注意,我将表格别名更改为比任意字母更有意义。

    编辑:

    考虑到表格的大小,我认为明确的join 可能会更好:

    SELECT c.actorId, COUNT(*)
    FROM watched w JOIN
         cast c
         ON w.movieId = c.movieId
    WHERE w.userId = 8
    GROUP BY c.actorId;
    

    对于此查询,您需要watched(userId, movieId) 和cast(movieId, actorId) 上的索引。此版本假定您在 watched 中没有重复行。

    【讨论】:

      【解决方案2】:

      也许使用内连接而不是存在会为您提供更好的性能。假设 movieId 和 userId 已编入索引,请尝试使用嵌套 where 子句中的过滤器进行内部连接:

      Select .....
      From 
        cast c inner join watched w
        On w.movieid = c.movieid
        And w.userid = 8
      Group by ....
      

      .

      从理论上讲,上述操作应该是一种成本较低的操作,因为每个记录都没有在存在子句中进行测试。

      请原谅缺少样式,我是从 iPad 上发布的。

      【讨论】:

        猜你喜欢
        • 2015-11-10
        • 2020-03-18
        • 1970-01-01
        • 1970-01-01
        • 2015-08-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多