我的生产表包含超过一百万条记录。需求要求分页查询通过OFFSET和LIMIT参数(类似于MySql的LIMIT子句)检索记录,而不对结果集进行排序,就像行的自然顺序在表扫描中一样,因为'ORDER BY'会产生不可接受的性能影响,包括ROW_NUMBER()OVER(ORDER BY ...)的传统技术中使用的'ORDER BY'子句。
任何专家都能解决这个问题吗?在没有任何结果集排序的情况下分页记录。
e.g。
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'
答案 0 :(得分:3)
除了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()。
答案 1 :(得分: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聚集索引可以按所需顺序传递行。
答案 2 :(得分:0)
如果仍然没有找到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
&#34; 0 AS alias_sort &#34;提供父查询中ORDER BY子句中使用的常量列。顶部外部查询提供过滤器并删除代理alias_rownum和alias_sort内部列。