优化此查询。与DBA在社交网络/社区类型网站上工作相关

时间:2009-08-17 11:16:28

标签: sql-server tsql

我认为这是社交网络和社区类型网站中常见的SP。 我有这个SP,它会在当前在线的那些朋友页面顺序上返回所有用户的朋友,然后按字母顺序返回。这需要很长时间才能加载,我希望加快速度。

我记得在某处读取将多个连接分解为较小的结果集可能会加快它的速度。我还没有尝试过,但我很想知道其他建议可能对此程序有什么影响。

DECLARE @userID INT -- This variable is parsed in
DECLARE @lastActivityMinutes INT

SET @lastActivitytMinutes = '15'

SELECT 
    Active = CASE WHEN DATEDIFF("n", b.LastActivityDate ,GETDATE()) < @lastActivityMinutes THEN 1 ELSE 0 END, 
    a.DisplayName, a.ImageFile, a.UserId, b.LastActivityDate
FROM 
    Profile AS a 
        INNER JOIN aspnet_Users as b on b.userId = a.UserId  
        LEFT JOIN Friend AS x ON x.UserID = a.UserID
        LEFT JOIN Friend AS z ON z.FriendID = a.UserID
WHERE   ((x.FriendId = @userID AND x.status = 1) -- Status = 1 means friendship accepted
        OR (z.UserID = @userID AND z.Status = 1))
GROUP BY a.userID, a.DisplayName, a.ImageFile, a.UserId, b.LastActivityDate
ORDER BY Active DESC, DisplayName ASC

我不确定如何剪辑我的执行计划,但主要的瓶颈似乎发生在MERGE JOIN(右外部加入),这花费了我29%。在不同阶段,Parallelism的成本也分别为9%,6%,5%和9%,总计29%。

我最初的想法是首先使用CTE从Profile和aspnet表返回JOINED结果,然后将LEFT JOINS连接到Friends表。

1 个答案:

答案 0 :(得分:3)

您使用Friend加入LEFT JOIN两次,然后删除NULLLEFT JOIN条件返回的WHERE,然后使用GROUP BY来摆脱区别。

这不是最好的查询。

你为什么不用这个:

SELECT  Active = CASE WHEN DATEDIFF("n", b.LastActivityDate ,GETDATE()) < @lastActivityMinutes THEN 1 ELSE 0 END,
        a.DisplayName, a.ImageFile, a.UserId, b.LastActivityDate
FROM    (
        SELECT  FriendID
        FROM    Friends
        WHERE   UserID = @UserId
                AND status = 1
        UNION
        SELECT  UserID
        FROM    Friends
        WHERE   FriendID = @UserId
                AND status = 1
        ) x
INNER JOIN
        Profile AS a 
ON      a.UserID = x.FriendID
INNER JOIN
        aspnet_Users as b
ON      b.userId = a.UserId
ORDER BY
        Active DESC, DisplayName ASC