Answered by:
Server Side Paging ( Best General Practice )

Question
-
I just searched : "Server Side Paging" on this forum and multiple existing threads pulled up with nice suggestions. However I came here in particular with following two approaches in my mind I tried to observe the execution plans but that is not my cup of tea to be honest, so I am requesting y'all to get me started with making decisions instead asking. ( Give a man a fish, and you feed him for a day; show him how to catch fish, and you feed him for a lifetime. )
Basically I need to decide the best query from performance point of view.
I've tried to use Northwind database instead our Legacy DB so there might a (some) filter(s) that might not make sense but I am trying to "reproduce" quite similar query as I can.
SQL Server 2008 R2
Query 1 :
USE Northwind; DECLARE @page_size INT; DECLARE @current_page INT; SET @page_size = 20; SET @current_page = 3; WITH Paging AS ( SELECT rn = ROW_NUMBER() OVER ( ORDER BY OrderID ) ,* FROM dbo.Orders WHERE Freight > 0 ) SELECT TOP (@page_size) PG.* FROM Paging PG WHERE PG.rn > ((@current_page * @page_size) - (@page_size))
Query 2 :
USE Northwind; DECLARE @page_size INT; DECLARE @current_page INT; SET @page_size = 20; SET @current_page = 3; SELECT TOP (@page_size) * FROM dbo.Orders WHERE Freight > 0 AND OrderID NOT IN ( SELECT TOP ((@page_size) * ((@current_page) - 1)) OrderID FROM dbo.Orders )
Thanks !
- Edited by Aarsh (MCTS) Friday, January 3, 2014 5:25 AM
Friday, January 3, 2014 5:20 AM
Answers
-
I believe the the Query using a CTE is efficient. I looked at the IO Statistics and looks like the Query with CTE results in much less reads. Here is my comparison.
Without CTE
--Run 1 (20 row(s) affected) Table 'Orders'. Scan count 2, logical reads 7, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. (1 row(s) affected) --Run 2 (20 row(s) affected) Table 'Orders'. Scan count 2, logical reads 9, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. (1 row(s) affected) --Run 3 (20 row(s) affected) Table 'Orders'. Scan count 2, logical reads 43, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. (1 row(s) affected)
With CTE
--Run 1 (20 row(s) affected) Table 'Orders'. Scan count 1, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. (1 row(s) affected) --Run 2 (20 row(s) affected) Table 'Orders'. Scan count 1, logical reads 5, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. (1 row(s) affected) --Run 3 (20 row(s) affected) Table 'Orders'. Scan count 1, logical reads 22, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. (1 row(s) affected)
Satheesh
My Blog
Friday, January 3, 2014 5:59 AM
All replies
-
I believe the the Query using a CTE is efficient. I looked at the IO Statistics and looks like the Query with CTE results in much less reads. Here is my comparison.
Without CTE
--Run 1 (20 row(s) affected) Table 'Orders'. Scan count 2, logical reads 7, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. (1 row(s) affected) --Run 2 (20 row(s) affected) Table 'Orders'. Scan count 2, logical reads 9, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. (1 row(s) affected) --Run 3 (20 row(s) affected) Table 'Orders'. Scan count 2, logical reads 43, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. (1 row(s) affected)
With CTE
--Run 1 (20 row(s) affected) Table 'Orders'. Scan count 1, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. (1 row(s) affected) --Run 2 (20 row(s) affected) Table 'Orders'. Scan count 1, logical reads 5, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. (1 row(s) affected) --Run 3 (20 row(s) affected) Table 'Orders'. Scan count 1, logical reads 22, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. (1 row(s) affected)
Satheesh
My Blog
Friday, January 3, 2014 5:59 AM -
Check following blog post which shows Pagination by using CTEs: http://sqlwithmanoj.wordpress.com/2011/12/30/creating-stored-procedures-with-dynamic-search-paging-pagination/
If you are on SQL Server 2012, then you can use the new OFFSET-FETCH clause, check this blog post: http://sqlwithmanoj.wordpress.com/2011/07/28/tsql-denali-new-feature-offset-fetch-clause-for-pagingpagination/
~manoj | email: http://scr.im/m22g
http://sqlwithmanoj.wordpress.com
MCCA 2011 | My FB PageFriday, January 3, 2014 6:04 AM -
Paging with row_number() (SQL 2005 & on):
http://www.sqlusa.com/bestpractices2005/payregister/
Kalman Toth Database & OLAP Architect IPAD SELECT Query Video Tutorial 3.5 Hours
New Book / Kindle: Exam 70-461 Bootcamp: Querying Microsoft SQL Server 2012Saturday, January 4, 2014 10:16 PM