2011-03-17 71 views
5

在stackoverflow上有很多sql server分页问题,​​他们中的很多人都在谈论使用ROW_NUMBER() OVER (ORDER BY ...) AND CTE。一旦进入成千上万的行并开始在非主键值上添加排序并添加自定义的WHERE子句,这些方法就会变得非常不便。我有一个包含数百万行的数据集,我试图通过自定义排序和筛选来进行翻页,但是我的性能很差,甚至在我排序和筛选的所有字段上都有索引。我甚至尽可能在每个索引中包含我的SELECT列,但这几乎没有帮助,并严重臃肿了我的数据库。Microsoft SQL Server寻呼

我注意到,无论您点击什么排序标准或页码,stackoverflow分页只需要大约500毫秒。任何人都知道如何在数百万行的SQL Server 2008中高效地进行分页工作?这将包括尽可能有效地获取总行数。

我的当前查询具有完全相同的逻辑有关寻呼这个计算器的问题: Best paging solution using SQL Server 2005?

+0

您可以发布查询的任何机会;一般原则是一个很好的人,但他在现实世界中存在问题;) – u07ch 2011-03-17 07:14:00

+0

不在每个想要排序(或筛选)的列上添加索引,有帮助吗?这似乎很明显,但我不知道你是否尝试过。 – bart 2011-03-17 08:05:53

+0

我确实在所有列上都有索引。超过前几千的分页后,查询时间开始线性上升... – jjxtra 2011-06-14 05:36:29

回答

5

任何人都知道如何使呼叫有效地工作在SQL Server 2008与数百万行的?

如果您想要精确完美的分页,那么为每个记录建立一个索引键(位置行号)是不可替代的。但是,还有其他选择。

(1)总页数(记录)

  • 您可以使用近似从sysindexes.rows(几乎即时)假设的变化率小。
  • 可以使用触发器来保持一个完全准确的,到第二,表中的行数

(2)寻呼

(一)
可以显示页面跳转中说,在未来五年页在记录的任何一边。这些需要在每边最多扫描{页面大小} x 5。如果您的基础查询适合快速沿着排序顺序旅行,这应该不会太慢。因此,考虑记录X,你可以使用到前一个页面(假设排序顺序是a asc, b desc

select top(@pagesize) t.* 
from tbl x 
inner join tbl t on (t.a = x.a and t.b > x.b) OR 
        (t.a < a.x) 
where x.id = @X 
order by t.a asc, t.b desc 

(即最后的前X个记录)

{页面大小}若要去五页回,您将其增加到TOP(@ pagesize * 5),然后再从该子查询中进一步选择TOP(@pagesize)。

缺点:此选项要求您无法直接跳转到特定位置,您的选项只有第一(简单) ,LAST(easy),NEXT/PRIOR,<每页5页

(b)
如果分页总是非常具体和可预测的,请维护INDEXED视图或触发器更新的表,该表不包含行号中的空位。如果表格通常只能看到频谱一端的更新,那么这可能是一种选择,通过移动不太多的记录可以快速轻松地填充删除的差距。

这种方法为您提供了一个rowcount(最后一行),也可以直接访问任何页面。

+0

这是非常深思熟虑的,谢谢我会尝试一些这些东西 – jjxtra 2011-03-17 08:16:41

+1

当结果总数较小(小于100K)时,我最终做的是使用我的Lucene索引进行分页。当它更高时,我使用SQL Server。 Sql服务器在大表中寻找分页小结果集。 Lucene非常适合在较大的数据集中分页较小的结果集。 – jjxtra 2012-02-13 18:32:18

+0

不妨将此标记为正确,因为它与使用SQL Server时可以获得的一样好。我上面提到的混合方法工作得很好。 – jjxtra 2012-05-25 21:14:40