ROW_NUMBER() 查询计划排序优化
ROW_NUMBER() Query Plan SORT Optimization
下面的查询访问包含超过 3000 万行的投票 table。然后使用 WHERE n = 1
选择结果集。在查询计划中,ROW_NUMBER() 窗口函数中的 SORT 操作占查询成本的 95%,并且需要 6 分钟以上才能完成执行。
我已经在 same_voter, eid, country include vid, nid, sid, vote, time_stamp, new
上有一个索引来覆盖 where 子句。
是更正此问题以在 vid, nid, sid, new DESC, time_stamp DESC
上添加索引的最有效方法,还是有替代方法来使用 ROW_NUMBER() 函数以更有效地实现相同的结果方式?
SELECT v.vid, v.nid, v.sid, v.vote, v.time_stamp, v.new, v.eid,
ROW_NUMBER() OVER (
PARTITION BY v.vid, v.nid, v.sid ORDER BY v.new DESC, v.time_stamp DESC) AS n
FROM dbo.Votes v
WHERE v.same_voter <> 1
AND v.eid <= @EId
AND v.eid > (@EId - 5)
AND v.country = @Country
使用 ROW_NUMBER()
的一种可能替代方法:
SELECT
V.vid,
V.nid,
V.sid,
V.vote,
V.time_stamp,
V.new,
V.eid
FROM
dbo.Votes V
LEFT OUTER JOIN dbo.Votes V2 ON
V2.vid = V.vid AND
V2.nid = V.nid AND
V2.sid = V.sid AND
V2.same_voter <> 1 AND
V2.eid <= @EId AND
V2.eid > (@EId - 5) AND
V2.country = @Country AND
(V2.new > V.new OR (V2.new = V.new AND V2.time_stamp > V.time_stamp))
WHERE
V.same_voter <> 1 AND
V.eid <= @EId AND
V.eid > (@EId - 5) AND
V.country = @Country AND
V2.vid IS NULL
查询基本上是说要获取所有符合您的条件的行,然后连接到任何其他符合相同条件的行,但根据 new
和 [=13,这些行对于分区来说排名更高=] 列。如果找到 none,那么这一定是您想要的行(排名最高),如果找到 none,则意味着 V2.vid
将是 NULL
。我假设 vid
否则永远不会是 NULL
。如果它是 table 中的 NULL
able 列,那么您需要调整查询的最后一行。
下面的查询访问包含超过 3000 万行的投票 table。然后使用 WHERE n = 1
选择结果集。在查询计划中,ROW_NUMBER() 窗口函数中的 SORT 操作占查询成本的 95%,并且需要 6 分钟以上才能完成执行。
我已经在 same_voter, eid, country include vid, nid, sid, vote, time_stamp, new
上有一个索引来覆盖 where 子句。
是更正此问题以在 vid, nid, sid, new DESC, time_stamp DESC
上添加索引的最有效方法,还是有替代方法来使用 ROW_NUMBER() 函数以更有效地实现相同的结果方式?
SELECT v.vid, v.nid, v.sid, v.vote, v.time_stamp, v.new, v.eid,
ROW_NUMBER() OVER (
PARTITION BY v.vid, v.nid, v.sid ORDER BY v.new DESC, v.time_stamp DESC) AS n
FROM dbo.Votes v
WHERE v.same_voter <> 1
AND v.eid <= @EId
AND v.eid > (@EId - 5)
AND v.country = @Country
使用 ROW_NUMBER()
的一种可能替代方法:
SELECT
V.vid,
V.nid,
V.sid,
V.vote,
V.time_stamp,
V.new,
V.eid
FROM
dbo.Votes V
LEFT OUTER JOIN dbo.Votes V2 ON
V2.vid = V.vid AND
V2.nid = V.nid AND
V2.sid = V.sid AND
V2.same_voter <> 1 AND
V2.eid <= @EId AND
V2.eid > (@EId - 5) AND
V2.country = @Country AND
(V2.new > V.new OR (V2.new = V.new AND V2.time_stamp > V.time_stamp))
WHERE
V.same_voter <> 1 AND
V.eid <= @EId AND
V.eid > (@EId - 5) AND
V.country = @Country AND
V2.vid IS NULL
查询基本上是说要获取所有符合您的条件的行,然后连接到任何其他符合相同条件的行,但根据 new
和 [=13,这些行对于分区来说排名更高=] 列。如果找到 none,那么这一定是您想要的行(排名最高),如果找到 none,则意味着 V2.vid
将是 NULL
。我假设 vid
否则永远不会是 NULL
。如果它是 table 中的 NULL
able 列,那么您需要调整查询的最后一行。