下面的查询访问包含超过3000万行的Votes表。然后使用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
答案 0 :(得分:1)
使用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
和time_stamp
对分区进行排名更高的行列。如果没有找到,那么这必须是您想要的行(它排名最高),如果找不到,则表示V2.vid
将是NULL
。我假设vid
否则永远不会NULL
。如果它是您表格中的NULL
能列,那么您需要调整查询的最后一行。