Reputation: 1
A production table of mine contains over a million records. An requirement calls for a paging query to retrieve records by OFFSET and LIMIT parameters(similar to MySql's LIMIT clause), without sorting the result set, just as rows' natural order are in a table-scan, since 'ORDER BY' generates unacceptable performance impact, including 'ORDER BY' clause used in traditional technique of ROW_NUMBER() OVER (ORDER BY ...).
Could any expert offer a solution to this problem? Paging records without any ordering of the result set.
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'
Upvotes: 0
Views: 4567
Reputation: 1507
If you still find no column for ORDER BY, you may sort by a constant column you add just to get the query working:
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" provides the constant column used in the ORDER BY clause in the parent query. Top outer query provides the filter and gets rid of both surrogate alias_rownum and alias_sort inner columns.
Upvotes: 0
Reputation: 238086
This is just meant as a comment in addition to Remus' answer.
Paging a primary key doesn't cause SQL Server to sort, because the primary key is stored in sort order. You can page on primary key without a WITH statement like:
SELECT *
FROM (
SELECT
ROW_NUMBER() OVER (ORDER BY PrimaryKey) as rn
, *
FROM BigTable
) sub
WHERE sub.rn BETWEEN 3 and 7
The subquery is still required, because you can't use ROW_NUMBER() in a WHERE statement.
Upvotes: 3
Reputation: 294287
ORDER BY only generates additional impact if it cannot be addressed by an index. If you see 'unacceptable' impact it means that either you did not properly design your table, or you did not properly design the query.
Some us constant ORDER BY expressions SELECT ..., ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM ...
. But that may still generate a sorting spool if not properly designed.
So to consider your example:
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;
This will not sort the data because the recordId PK clustered index can deliver the rows in the needed order.
Upvotes: 2