Share via

better Paging techniques without using offset

mehmood tekfirst 771 Reputation points
2022-08-04T08:16:55.597+00:00

Hi,

I want to replace this paging technique with a high performance solution. Please see and suggest.

SET ANSI_NULLS ON  
GO  
SET QUOTED_IDENTIFIER ON  
GO  
ALTER PROCEDURE [dbo].[spGetAllList] 	  
	@Take int = 0,  
	@Skip int = 0	  
AS  
BEGIN  
  
Declare @fromRow int = @Take * (@Skip);  
Declare @toRow int = @Take * (@Skip +1);  
  
  
        Select cn.Id,cn.CustomerName, cn.AgrNumber, cn.ResNumber, c.Id CarId, c.Make, c.Model, c.Group, c.Tariff, cn.StartDate, cn.EndDate  
        From Contract cn   
        Left Join Cars c on cn.CarId = c.Id  
	Order By CAST(cn .AgrNumber as int) DESC	, CAST(cn .ResNumber as int) DESC  
	OFFSET @fromRow ROWS  
	FETCH NEXT @Take ROWS ONLY;  
  
END  
END  

I want to re-write this paging logic through offset which should be better from it and can achieve more performance.

Developer technologies | Transact-SQL
Developer technologies | Transact-SQL

A Microsoft extension to the ANSI SQL language that includes procedural programming, local variables, and various support functions.


Answer accepted by question author

LiHong-MSFT 10,061 Reputation points
2022-08-04T08:40:57.043+00:00

Hi @mehmood tekfirst
Try this:

;WITH CTE AS  
(      
 Select cn.Id,cn.CustomerName, cn.AgrNumber, cn.ResNumber, c.Id CarId, c.Make, c.Model, c.Group, c.Tariff, cn.StartDate, cn.EndDate  
       ,ROW_NUMBER() OVER(ORDER BY CAST(cn .AgrNumber as int) DESC , CAST(cn .ResNumber as int) DESC) AS PageIndex  
 From Contract cn Left Join Cars c on cn.CarId = c.Id  
)  
SELECT *  
FROM CTE  
WHERE PageIndex > @fromRow AND PageIndex <= @toRow  

Best regards,
LiHong


If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
Note: Please follow the steps in our Documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

Was this answer helpful?

1 person found this answer helpful.

2 additional answers

Sort by: Most helpful
  1. Tom Phillips 17,786 Reputation points
    2022-08-04T16:48:13.417+00:00

    Your performance issue is not in the OFFSET/FETCH. To do paging it must run the entire query, and sort it to find the window you want to return. That part is the same regardless of your method. You need to tune your query.

    What is the data type of AgrNumber and ResNumber? Why are you casting them to INT in the order by? Is there a proper index created?

    Was this answer helpful?

    4 people found this answer helpful.

  2. Erland Sommarskog 134.4K Reputation points MVP Volunteer Moderator
    2022-08-04T22:22:56.497+00:00

    I guess the problem is here:

       Order By CAST(cn .AgrNumber as int) DESC    , CAST(cn .ResNumber as int) DESC  
    

    What are the actual data types of these columns? What indexes are there on the table?

    I would guess that the execution plan results in a full sort of the data every time. If you would have a clustered index on these columns, and their data type would be int, so the CAST is not needed., the SP would only have to read @Take * (@skip + 1) rows.

    Was this answer helpful?

    2 people found this answer helpful.

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.