【发布时间】:2011-02-18 00:34:39
【问题描述】:
我有一个 SQL Server 2008 CTE,它负责返回一个位置的 Top Review。
CTE 包装在 UDF(表值)中,并加入 LocationId 字段,因此我可以获得每个位置的最高评价。
基数:
1 位置有 0-many 个 PostLocations
1 个帖子位置有 1 个帖子
1 帖子有 1 评论
这是 UDF:
CREATE FUNCTION [dbo].[Review_HighestRated_Aggregated_ByLocation]
(
)
RETURNS TABLE
AS
RETURN
(
WITH [RankedLocations] AS
(
SELECT PL.LocationId,
R.Rating,
P.PostID,
P.UniqueUri,
P.Content,
ROW_NUMBER() OVER (PARTITION BY PL.LocationId ORDER BY R.Rating DESC, P.LocationTypeId, P.CreatedOn DESC) As ScoreRank
From dbo.PostLocations As PL
INNER JOIN dbo.Posts As P
ON P.PostId = PL.PostId
INNER JOIN dbo.Reviews As R
ON R.PostId = P.PostId
WHERE R.ReviewTypeId <> 5
AND P.Content IS NOT NULL
)
SELECT LocationId, Rating, PostID, UniqueUri, Content
FROM RankedLocations
WHERE ScoreRank = 1
)
这是我如何使用它的示例:
select l.LocationId, l.Name, l.UniqueUri, r.UniqueUri, r.Content
from @Locations l -- temp table containing around 18 location ids
inner join dbo.Review_HighestRated_Aggregated_ByLocation() r
on l.LocationId = r.LocationId
执行上述查询需要 15 秒,这是不可接受的。如果不加入 UDF,则需要 0 秒。
关于如何改进它的任何想法?
如果我查看执行计划,SORT 占据了 98% 的执行成本。此操作的 IO/子树成本约为 300。
我希望执行计划能给我一个提示,让我知道我可以创建一个索引来降低成本,但我什么也没得到。
有什么想法吗?
【问题讨论】:
-
R.ReviewTypeId上有索引吗?您是否有用于外键关系的列的索引(三个表中的PostId)?另外:另一种选择是尝试直接在查询中使用 CTE,而不是在 UDF 中“隐藏”它(这可能非常慢......) - 这有什么不同吗?? -
@marc_s。是的,ReviewTypeId 上有一个索引。是的,PostId 是 Posts 上的集群 PK、PostLocations 上的集群 PK 和评论上的集群 PK 的一部分。我也试过直接使用CTE,没有变化。我尝试创建一个视图,这很好 - 但您不能索引其中包含聚合操作或子查询的视图。目前,我倾向于使用 sql 计划作业每隔一小时左右更新一次的“缓存表”。想法?
标签: performance tsql sql-server-2008 common-table-expression sql-execution-plan