【问题标题】:Server side paging in SQL ServerSQL Server 中的服务器端分页
【发布时间】:2013-01-01 07:32:42
【问题描述】:

我对 SQL Server 如何使用公用表表达式和 ROW_NUMBER 实现更少的读取和性能改进感到有些困惑。为什么在表达式中实现的表不必执行普通查询必须执行的所有读取以允许查询使用 ROW_NUMBER 进行排序?

【问题讨论】:

  • 你在比较什么其他的解决方案?
  • 本质上只是一个不使用行号分页的查询

标签: sql-server-2008 row-number


【解决方案1】:

CTE 没有(必然)“实现”。并不是说它会不可避免地将所有行复制到其他地方,并且会在副本上执行其他操作(尽管它可能会表现得如此,因此优化器认为它更好)。

如果我们采用这个简单的查询:

SELECT  *
FROM    (
        SELECT  *,
                ROW_NUMBER() OVER (ORDER BY id) rn
        FROM    mytable
        ) q
WHERE   rn BETWEEN 101 AND 110

看看它的计划,我们会看到这样的东西:

  |--Filter(WHERE:([Expr1003]>=(101) AND [Expr1003]<=(110)))
       |--Top(TOP EXPRESSION:(CASE WHEN (110) IS NULL OR (110)<(0) THEN (0) ELSE (110) END))
            |--Sequence Project(DEFINE:([Expr1003]=row_number))
                 |--Segment
                      |--Clustered Index Scan(OBJECT:([ee].[dbo].[mytable].[PK__mytable__3213E83F29C2D227]), ORDERED FORWARD)

在这里,记录被扫描(按id 的顺序,因为表聚集在id 上),分配ROW_NUMBER(这是Sequence Project 所做的)并传递给TOP,这只是暂停达到某个阈值时执行(在我们的例子中为110 记录)。

这 110 条记录被传递给 Filter,它只传递 rn 大于 100 的记录。

查询本身只扫描110记录:

SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 1 ms.

(строк обработано: 10)
Table 'mytable'. Scan count 1, logical reads 3, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

3 页。

现在让我们看看未分页的查询:

SELECT  *
FROM    mytable
ORDER BY
        id

这个非常简单:读取表格中的所有内容并将其吐出。

  |--Clustered Index Scan(OBJECT:([ee].[dbo].[mytable].[PK__mytable__3213E83F29C2D227]), ORDERED FORWARD)

但是,看起来容易并不意味着容易完成。表很大,我们需要多次读取才能返回所有记录:

SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

(строк обработано: 1310720)
Table 'mytable'. Scan count 1, logical reads 2765, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 266 ms,  elapsed time = 11690 ms.

所以,简而言之,分页查询只知道何时停止。

【讨论】:

  • 在查询按例如计算字段排序的情况下是否仍然如此?例如在我们的例子中,我们有一组结果,这些结果按与某个位置的接近程度排序。为了正确地对结果进行排序和分页,似乎必须对每条记录进行评估。
  • @MatthewEvans:如果您想按邻近度排序,则需要使用空间索引。不幸的是,它们在 SQL Server 中不能很好地工作,因此最好使用自己的平铺算法。
  • 是的 - 我们尝试了地理类型并遇到了性能问题。所以我们使用我们自己的用户定义的距离函数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-03
  • 1970-01-01
  • 2016-05-04
  • 1970-01-01
相关资源
最近更新 更多