我有一个表保持项目之间的父子关系。这些可以随着时间的推移而改变,有必要保留完整的历史记录,以便我可以随时查询关系。
表格是这样的(我删除了一些列和主键等以减少噪音):
CREATE TABLE [tblRelation](
[dtCreated] [datetime] NOT NULL,
[uidNode] [uniqueidentifier] NOT NULL,
[uidParentNode] [uniqueidentifier] NOT NULL
)
我在特定时间获取关系的查询是这样的(假设@dt是具有所需日期的日期时间):
SELECT *
FROM (
SELECT ROW_NUMBER() OVER (PARTITION BY r.uidNode ORDER BY r.dtCreated DESC) ix, r.*
FROM [tblRelation] r
WHERE (r.dtCreated < @dt)
) r
WHERE r.ix = 1
此查询效果很好。但是,性能还不如我想的那么好。在查看执行计划时,它基本上归结为聚集索引扫描(成本的36%)和排序(成本的63%)。
我应该使用哪些索引来加快查询速度?或者是否有更好的方法在此表上执行此查询?
答案 0 :(得分:3)
此查询的理想索引是使用键列uidNode
,dtCreated
,并在表中包含列,以便在返回r.*
时使索引覆盖。如果查询通常只返回相对较少的行(看起来可能是由于WHERE r.ix = 1
过滤器),那么可能不值得使索引覆盖,因为密钥查找的成本可能不会超过负数大索引对CUD语句的影响。
答案 1 :(得分:1)
SQL Server 2005上的窗口/排名函数有时不是最优的(基于此处的答案)。在SQL Server 2008中显然更好
另一种选择是这样的。我在(uidNode,dtCreated)上有一个非聚集索引INCLUDE SELECT所需的任何其他列。取决于马丁史密斯所说的查找。
WITH MaxPerUid AS
(
SELECT
MAX(r.dtCreated) AS MAXdtCreated, r.uidNode
FROM
MaxPerUid
WHERE
r.dtCreated < @dt
GROUP BY
r.uidNode
)
SELECT
...
FROM
MaxPerUid M
JOIN
MaxPerUid R ON M.uidNode = R.uidNode AND M.MAXdtCreated = R.dtCreated