hun*_*m06 19 sql sql-server performance
我希望在表格中获得第n个到第m个记录,以下2个解决方案中的最佳选择:
解决方案1:
SELECT * FROM Table WHERE ID >= n AND ID <= m
Run Code Online (Sandbox Code Playgroud)
解决方案2:
SELECT * FROM
(SELECT *,
ROW_NUMBER() OVER (ORDER BY ID) AS row
FROM Table
)a
WHERE row >= n AND row <= m
Run Code Online (Sandbox Code Playgroud)
Rem*_*anu 55
正如其他人已经指出的那样,查询会返回不同的结果并将苹果与橙子进行比较.
但潜在的问题仍然存在:哪个更快:密钥集驱动的分页或rownumber驱动的分页?
键集驱动的分页依赖于记住最后显示的页面的顶部和底部键,并根据顶部/最后一个键集请求下一组或上一组行:
下一页:
select top (<pagesize>) ...
from <table>
where key > @last_key_on_current_page
order by key;
Run Code Online (Sandbox Code Playgroud)
上一页:
select top (<pagesize>)
from <table>
where key < @first_key_on_current_page
order by key desc;
Run Code Online (Sandbox Code Playgroud)
与ROW_NUMBER方法或MySQL的等效LIMIT方法相比,这种方法有两个主要优点:
但是,这种方法很难实现,普通程序员很难理解,也没有工具支持.
这是Linq查询引入的常用方法:
select ...
from (
select ..., row_number() over (...) as rn
from table)
where rn between @firstRow and @lastRow;
Run Code Online (Sandbox Code Playgroud)
(或使用TOP的类似查询)这种方法易于实现,并且由工具(特别是Linq .Limit和.Take运算符)支持.但是这种方法可以保证扫描索引以计算行数.这种方法对于第1页通常非常快,并且随着一个页面越来越高而逐渐减慢.
作为奖励,使用此解决方案很容易更改排序顺序(只需更改OVER子句).
总的来说,考虑到基于ROW_NUMBER()的解决方案的简易性,他们从Linq获得的支持,使用任意订单进行中等数据集的简单性,基于ROW_NUMBER的解决方案就足够了.对于大型和超大型数据集,ROW_NUMBER()可能会出现严重的性能问题.
另一件需要考虑的事情是,通常有一定的访问模式.通常,前几页很热,而10之后的页面基本上从未被查看过(例如,最近的帖子).在这种情况下,可以很好地忽略ROW_NUMBER()用于访问底页(显示页面,其中必须计算大量行以获得起始结果行)的惩罚.
最后,键集分页非常适合字典导航,ROW_NUMBER()无法轻松容纳.字典导航是用户可以导航到某些锚点而不是使用页码,而不是使用页码.典型示例是联系人Rolodex(如侧边栏),单击M并导航到以M开头的第一个客户名称.
Sco*_*vey 11
第二个答案是您的最佳选择.它考虑到您的ID列中可能存在漏洞的事实.我将它重写为CTE而不是子查询...
;WITH MyCTE AS
(SELECT *,
ROW_NUMBER() OVER (ORDER BY ID) AS row
FROM Table)
SELECT *
FROM MyCTE
WHERE row >= @start
AND row <= @end
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
12289 次 |
| 最近记录: |