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 中的 NULLable 列,那么您需要调整查询的最后一行。