我认为这是社交网络和社区类型网站中常见的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表。
答案 0 :(得分:3)
您使用Friend
加入LEFT JOIN
两次,然后删除NULL
按LEFT 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