Sql server 分组方式上的MSSQL联接速度太慢

Sql server 分组方式上的MSSQL联接速度太慢,sql-server,database,optimization,join,subquery,Sql Server,Database,Optimization,Join,Subquery,我在MSSQL中有以下查询 SELECT TOP 50 CustomerID FROM Ratings WHERE CustomerID != 915 AND MovieID IN (SELECT DISTINCT MovieID FROM Ratings WHERE CustomerID = 915) GROUP BY CustomerID ORDER BY count(*) DESC 它超快。当我尝试在这样的子查询中使用它时 SELECT * FROM Ratings WHERE Movi

我在MSSQL中有以下查询

SELECT TOP 50 CustomerID FROM Ratings
WHERE CustomerID != 915
AND MovieID IN (SELECT DISTINCT MovieID FROM Ratings WHERE CustomerID = 915)
GROUP BY CustomerID
ORDER BY count(*) DESC
它超快。当我尝试在这样的子查询中使用它时

SELECT * FROM Ratings
WHERE MovieID = 1 AND
CustomerID IN (SELECT TOP 50 CustomerID FROM Ratings
    WHERE CustomerID != 915
    AND MovieID IN (SELECT DISTINCT MovieID FROM Ratings WHERE CustomerID = 915)
    GROUP BY CustomerID
    ORDER BY count(*) DESC)

你知道为什么这么慢吗?我怎样才能加快速度?我的主键是(MovieID CustomerID),我在CustomerID上添加了一个索引,您需要在
(CustomerID,MovieID)
(按此顺序)上创建一个额外的
唯一的
索引来改进此查询

有关性能详细信息,请参阅我博客中的文章:

由于子查询返回
唯一的
值集,因此可以将查询重写为
联接

SELECT  r2.*
FROM    (
        SELECT  TOP 50 CustomerID
        FROM    (
                SELECT  MovieID
                FROM    Ratings
                WHERE   CustomerID = 915
                ) q
        JOIN    Ratings r
        ON      r.MovieID = q.MovieID
                AND CustomerID <> 915
        GROUP BY
                CustomerID
        ORDER BY
                COUNT(*) DESC
        ) ro
JOIN    Ratings r2
ON      r2.MovieID = 1
        AND r2.CustomerID = ro.CustomerID

令人惊叹的唯一的问题是,有时它的回报率略低于50,可能是因为一些顶尖人物还没有给电影ID 1评分。但我应该能搞定剩下的事。亲爱的,我的工作已经完成了。顺便说一句,查询分析器建议使用与您相同的索引,这很有帮助。
SELECT  r2.*
FROM    (
        SELECT  TOP 50 CustomerID
        FROM    (
                SELECT  MovieID
                FROM    Ratings
                WHERE   CustomerID = 915
                ) q
        JOIN    Ratings r
        ON      r.MovieID = q.MovieID
                AND CustomerID <> 915
                AND EXISTS
                (
                SELECT  1
                FROM    Ratings re
                WHERE   re.MovieID = 1
                        AND re.CustomerID = r.CustomerID
                )
        GROUP BY
                CustomerID
        ORDER BY
                COUNT(*) DESC
        ) ro
JOIN    Ratings r2
ON      r2.MovieID = 1
        AND r2.CustomerID = ro.CustomerID