SQL Server 2012 - Server side paging demo using OFFSET/FETCH NEXT

SQL Server 2005 introduced ROW_NUMBER() which provided an easy option to implement server side paging. SQL Server 2012 added another enhancement which made paging much simpler and efficient.

 

All the scripts in this demo assume that a database with name **NorthPole** exists in the current SQL Server instance. In case you do not have it, just create an empty database with the same name or edit the script below to point to a database where you would like to run the scripts.

01.USE NorthPole
02.GO
03. 
04.IF OBJECT_ID('Customers','U') IS NOT NULL
05.DROP TABLE Customers
06. 
07.CREATE TABLE Customers (
08.CustomerID INT,
09.CustomerNumber CHAR(4),
10.CustomerName VARCHAR(50),
11.CustomerCity VARCHAR(20) )
12.GO
13. 
14.INSERT INTO Customers (
15.CustomerID, CustomerNumber, CustomerName, CustomerCity
16.)
17.SELECT
18.Number,
19.REPLACE(STR(Number, 4), ' ', '0'),
20.'Customer ' + STR(number,6),
21.CHAR(65 + (number % 26)) + '-City'
22.FROM master..spt_values WHERE type = 'p'
23.AND number BETWEEN 0 AND 999

The above script will insert 1000 rows to the **Customers** table. We will use this data to run the demo scripts given below.

SQL Server 2005 introduced `ROW_NUMBER()` which provided an easy way to generate a sequence number in a result set, which was quite helpful to write queries that perform server-side-paging. In SQL Server 2005 and 2008, we can write a query such as the one given below.

01.USE NorthPole 
02.GO
03. 
04.DECLARE @page INT, @size INT
05.SELECT @page = 3, @size = 10
06. 
07.;WITH cte AS (
08.SELECT  TOP (@page * @size)
09.CustomerID,
10.CustomerName,
11.CustomerCity,
12.ROW_NUMBER() OVER(ORDER BY CustomerName ) AS Seq,
13.COUNT(*) OVER(PARTITION BY '') AS Total
14.FROM Customers
15.WHERE CustomerCity IN ('A-City','B-City')
16.ORDER BY CustomerName ASC
17.)
18.SELECT
19.*
20.FROM cte
21.WHERE seq BETWEEN (@page - 1 ) * @size + 1 AND @page * @size
22.ORDER BY seq
23. 
24./*
25.CustomerID  CustomerName   
26.----------- ----------------
27.260         Customer 260
28.261         Customer 261
29.286         Customer 286
30.287         Customer 287
31.312         Customer 312
32.313         Customer 313
33.338         Customer 338
34.339         Customer 339
35.364         Customer 364
36.365         Customer 365
37.*/

The above query returns 10 rows from the **customers** table. The query filters customers by the city specified and sorts the results by Customer name. Finally, rows from position 21 to 30 is returned.

SQL Server 2012 provides an easier syntax to achieve the above. We can use `OFFSET` to specify the starting position of the rows and `FETCH NEXT N` to specify the number of rows to retrieve from the `OFFSET`. Here is the new version of the above query.

01.USE NorthPole 
02.GO
03. 
04.DECLARE @page INT, @size INT
05.SELECT @page = 3, @size = 10
06. 
07.SELECT
08.*,
09.COUNT(*) OVER(PARTITION BY '') AS Total
10.FROM Customers
11.WHERE CustomerCity IN ('A-City','B-City')
12.ORDER BY CustomerID
13.OFFSET (@page -1) * @size ROWS
14.FETCH NEXT @size ROWS ONLY;

You may notice a performance difference between both versions of the query. When running both queries on the given sample data on my laptop, I am seeing that the approach using `ROW_NUMBER()` takes 60% of execution time and the new approach (using `OFFSET FETCH NEXT` takes only 40%).

Server side paging with SQL Server 2012

Keep in mind that the test data used in this demo is very simple and will be quite different from production scenarios. So it is important to run tests on your own test data with specific work load and server configuration before accurately assuming the performance statistics of each approach.

posted @ 2014-06-26 18:20  princessd8251  阅读(225)  评论(0)    收藏  举报