Sql Server 按偏移量分页行 - 没有'ORDER BY'

Posted

技术标签:

【中文标题】Sql Server 按偏移量分页行 - 没有\'ORDER BY\'【英文标题】:Sql Server paging rows by offset - without 'ORDER BY'Sql Server 按偏移量分页行 - 没有'ORDER BY' 【发布时间】:2009-10-31 15:28:39 【问题描述】:

我的生产表包含超过一百万条记录。要求分页查询通过 OFFSET 和 LIMIT 参数检索记录(类似于 mysql 的 LIMIT 子句),而不对结果集进行排序,就像行的自然顺序在表扫描中一样,因为“ORDER BY”会产生不可接受的性能影响,包括传统技术 ROW_NUMBER() OVER (ORDER BY ...) 中使用的“ORDER BY”子句。 有哪位专家可以提供解决这个问题的方法吗?对结果集没有任何排序的分页记录。 例如

Create table RandomRecords(int id, datetime recordDate)
----
select * from RandomRecords
34, '1/1/2009'
123, '8/1/2008'
11, '2/23/2008'
10, '3/2/2008'
4, '2/5/2009'
78, '1/1/2008'
55, '5/2/2008'
6666, '2/12/2009'
....
one million rows

-----
paging query with @Offset = 3 and @limit=4 generates
11, '2/23/2008'
10, '3/2/2008'
4, '2/5/2009'
78, '1/1/2008'

【问题讨论】:

你能对你的表结构做更多解释吗?似乎您的 RandomRecords 表是您的情况的过于简单化的示例。 【参考方案1】:

这只是对 Remus 回答的补充。

分页主键不会导致 SQL Server 排序,因为主键是按排序顺序存储的。您可以在没有 WITH 语句的情况下对主键进行分页,例如:

SELECT *
FROM (
    SELECT 
        ROW_NUMBER() OVER (ORDER BY PrimaryKey) as rn
    ,   *
    FROM BigTable
) sub 
WHERE sub.rn BETWEEN 3 and 7

子查询仍然是必需的,因为您不能在 WHERE 语句中使用 ROW_NUMBER()。

【讨论】:

【参考方案2】:

ORDER BY 只有在无法通过索引解决时才会产生额外的影响。如果您看到“不可接受”的影响,则意味着您没有正确设计您的表,或者您没有正确设计查询。

一些我们不变的 ORDER BY 表达式SELECT ..., ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM ...。但如果设计不当,仍可能会产生分拣线轴。

考虑一下你的例子:

CREATE TABLE RandomRecords (recordId int not null primary key, id int);
INSERT INTO RandomRecords (id) values (...)
WITH PagedRandomRecords (
   SELECT id, 
      ROW_NUMBER() OVER (ORDER BY recordId) as rn
      FROM RandomRecords)
SELECT id FROM PagedRandomRecords
   WHERE rn BETWEEN 3 and 7;

这将对数据进行排序,因为 recordId PK 聚集索引可以按所需顺序传递行。

【讨论】:

‒1 你是谁来确定什么是“不可接受的影响”【参考方案3】:

如果您仍然找不到 ORDER BY 的列,您可以按添加的常量列进行排序,以使查询正常工作:

SELECT col1, col2 FROM
   (SELECT col1, col2,
      ROW_NUMBER() OVER (ORDER BY alias_sort) AS alias_rownum
   FROM 
      (SELECT col1, col2, 0 AS alias_sort
      FROM 
         (SELECT col1, col2
         FROM ...)))
WHERE alias_rownum >= 12345 AND alias_rownum <= 67890

"0 AS alias_sort" 提供在父查询的 ORDER BY 子句中使用的常量列。顶部外部查询提供了过滤器并去掉了代理 alias_rownum 和 alias_sort 内部列。

【讨论】:

以上是关于Sql Server 按偏移量分页行 - 没有'ORDER BY'的主要内容,如果未能解决你的问题,请参考以下文章

大数据量分页问题优化sql代码

MySQL百万级数据量分页查询方法及其优化建议

sql优化之大数据量分页查询(mysql)

大数据量分页查询怎么优化提速?

MySQL大数据量分页查询优化

MySQL大数据量分页查询优化