1

全部,

我有一个包含大约 250000 条记录的用户表。我有以下查询(请注意,我是 SQL 新手),但执行需要很长时间。我检查了执行计划,执行时间的 %60 被 2 种占用。

SELECT TOP 50
    Flows_Users.UserName,
    Flows_Users.UserID,
    Flows_Users.ImageName,
    Flows_Users.DisplayName,
    Flows_UserBios.bio,
    FlowsCount = (
        SELECT Count(1)
        FROM Flows_Flows
        WHERE UserID = Flows_Users.UserID
            AND Flows_Flows.Active = '1'
    ),
    BeatsCount = (
        SELECT Count(1)
        FROM Flows_Beats
        WHERE UserName_ID = Flows_Users.UserID
            AND Flows_Beats.Active = '1'
    ),
    FollowersCount = (
        SELECT Count(1)
        FROM Flows_Follow
        WHERE FOLLOWING = Flows_Users.UserID
    ),
    FollowingCount = (
        SELECT Count(1)
        FROM Flows_Follow
        WHERE FOLLOWER = Flows_Users.UserID
    ),
    ISNULL(SUM(Flows_Flows_Likes_Dislikes.[Like]), 0) AS Likes,
    ISNULL(SUM(Flows_Flows_Likes_Dislikes.Dislike), 0) AS DisLikes
FROM Flows_Users
LEFT JOIN Flows_Flows
    ON Flows_Users.UserID = Flows_Flows.UserID
LEFT JOIN Flows_UserBios
    ON Flows_Users.UserID = Flows_UserBios.userid
LEFT JOIN Flows_Flows_Likes_Dislikes
    ON Flows_Flows.FlowID = Flows_Flows_Likes_Dislikes.FlowID
WHERE Flows_Users.UserID = Flows_Users.UserID
GROUP BY Flows_Users.UserID,
    Flows_Users.UserName,
    Flows_Users.ImagePath,
    Flows_Users.ImageName,
    Flows_Users.DisplayName,
    Flows_UserBios.bio
ORDER BY
    [Likes] DESC,
    [Dislikes] ASC,
    FlowsCount DESC

我知道这是一团糟,但是当桌子只有数万张时,它就完成了工作。有什么办法可以让这更快吗?现在执行最多需要 5-10 分钟。这也在一个存储过程中,我觉得我有需要索引、索引的列。

4

3 回答 3

1

正如@PreetSanght 建议的改变

这部分

FlowsCount = (
    SELECT Count(1)
    FROM Flows_Flows
    WHERE UserID = Flows_Users.UserID
        AND Flows_Flows.Active = '1'
),
BeatsCount = (
    SELECT Count(1)
    FROM Flows_Beats
    WHERE UserName_ID = Flows_Users.UserID
        AND Flows_Beats.Active = '1'
),
FollowersCount = (
    SELECT Count(1)
    FROM Flows_Follow
    WHERE FOLLOWING = Flows_Users.UserID
),
FollowingCount = (
    SELECT Count(1)
    FROM Flows_Follow
    WHERE FOLLOWER = Flows_Users.UserID
),

变成这样的东西

sum(case when Flows_Flows.Active = '1' then 1 else 0 end) 
over (partition by UserID order by Flows_Flows.UserID) as FlowsCount,

sum(case when Flows_Beats.Active = '1' then 1 else 0 end) 
over (partition by UserName_ID order by Flows_Flows.UserID) as BeatsCount,

count(1) over(parition by FOLLOWING order by Flows_Flows.UserID) as FollowersCount,
count(1) over(parition by FOLLOWER order by Flows_Flows.UserID) as FollowingCount,

我认为您
应该阅读有关窗口函数和 over() 子句的想法

如果您想要整个查询发布一些示例数据和表架构

于 2013-01-19T09:31:02.410 回答
0

试试这个改动,因为我没有那些表,你可能需要修补它。验证后,检查执行计划并查找表扫描。然后添加索引。如果数字索引很大,请考虑包含列。我个人会将其修改为视图而不是存储过程,但这是我的偏好。

有人曾经告诉我,计算 * 实际上稍微好一些,但那是在 SQL Server 2000 天里,不确定是否仍然相关。

如果可能,尽可能将左连接修改为内连接。IE。我假设用户没有被硬删除,因此会修改用户 ID 加入到内部并在必要时过滤禁用的帐户。

    SELECT TOP 50
    Flows_Users.UserName,
    Flows_Users.UserID,
    Flows_Users.ImageName,
    Flows_Users.DisplayName,
    Flows_UserBios.bio,
    a.FlowsCount,
    b.BeatsCount,
    c.FollowersCount,
    d.FollowingCount,
    ISNULL(SUM(Flows_Flows_Likes_Dislikes.[Like]), 0) AS Likes,
    ISNULL(SUM(Flows_Flows_Likes_Dislikes.Dislike), 0) AS DisLikes
FROM Flows_Users
LEFT JOIN     (    SELECT Count(*) FlowCount
        FROM Flows_Flows
        WHERE UserID = Flows_Users.UserID
            AND Flows_Flows.Active = '1') a
LEFT JOIN  (SELECT Count(*) as 
        FROM Flows_Beats
        WHERE UserName_ID = Flows_Users.UserID
            AND Flows_Beats.Active = '1') b
LEFT JOIN  (SELECT Count(*) as FollowersCount
        FROM Flows_Follow
        WHERE FOLLOWING = Flows_Users.UserID) c
LEFT JOIN  (
        SELECT Count(*) as FollowingCount
        FROM Flows_Follow
        WHERE FOLLOWER = Flows_Users.UserID) d
LEFT JOIN Flows_Flows
    ON Flows_Users.UserID = Flows_Flows.UserID
LEFT JOIN Flows_UserBios
    ON Flows_Users.UserID = Flows_UserBios.userid
LEFT JOIN Flows_Flows_Likes_Dislikes
    ON Flows_Flows.FlowID = Flows_Flows_Likes_Dislikes.FlowID
WHERE Flows_Users.UserID = Flows_Users.UserID
GROUP BY Flows_Users.UserID,
    Flows_Users.UserName,
    Flows_Users.ImagePath,
    Flows_Users.ImageName,
    Flows_Users.DisplayName,
    Flows_UserBios.bio
ORDER BY
    [Likes] DESC,
    [Dislikes] ASC,
    FlowsCount DESC
于 2013-01-19T09:18:41.597 回答
0

实现其他建议后,将查询转换为存储过程。这样,服务器不必在每次运行查询时都创建执行计划。

于 2013-01-19T09:24:16.603 回答