欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

分页存储过程效率对比

程序员文章站 2022-03-26 10:53:16
  1. 随便找了个网上效率被认为比较高的分页过程       if exists (select * from dbo.sy...

 

1. 随便找了个网上效率被认为比较高的分页过程

 

   

 if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[xp_getpager_user_dt]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)  
    drop procedure [dbo].[xp_getpager_user_dt]  
    GO  
    CREATE PROCEDURE [dbo].[xp_getpager_user_dt]  
    @pcount int output,    --总页数输出  
    @rcount int output,    --总记录数输出  
    @tablename nvarchar(100),    --查询表名  
    @keys varchar(50),        --主键  
    @fields nvarchar(500),    --查询字段  
    @where nvarchar(3000),    --查询条件  
    @sortfields nvarchar(100),    --排序字段  
    @beginindex int=0,        --开始位置  
    @pageindex int=1,        --当前页数  
    @pagesize int=100        --页大小  
    AS  
    SET NOCOUNT ON  
    SET ANSI_WARNINGS ON  
    IF @pagesize < 0 OR @pageindex < 0  
    BEGIN          
    RETURN  
    END  
    DECLARE @new_where1 NVARCHAR(3000)  
    DECLARE @new_order1 NVARCHAR(100)  
    DECLARE @new_order2 NVARCHAR(100)  
    DECLARE @Sql NVARCHAR(4000)  
    DECLARE @SqlCount NVARCHAR(4000)  
    DECLARE @Top int  
    if(@beginindex <=0)  
        set @beginindex=0  
    else  
        set @beginindex=@beginindex-1  
    IF ISNULL(@where,'') = ''  
        SET @new_where1 = ' '  
    ELSE  
        SET @new_where1 = ' WHERE ' + @where  
    IF ISNULL(@sortfields,'') <> ''   
    BEGIN  
        SET @new_order1 = ' ORDER BY ' + Replace(@sortfields,'desc','')  
        SET @new_order1 = Replace(@new_order1,'asc','desc')  
        SET @new_order2 = ' ORDER BY ' + @sortfields  
    END  
    ELSE  
    BEGIN  
        SET @new_order1 = ' ORDER BY ID DESC'  
        SET @new_order2 = ' ORDER BY ID ASC'  
    END  
    SET @SqlCount = 'SELECT @rcount=COUNT(1),@pcount=CEILING((COUNT(1)+0.0)/'  
                + CAST(@pagesize AS NVARCHAR)+') FROM ' + @tablename + @new_where1  
    EXEC SP_EXECUTESQL @SqlCount,N'@rcount INT OUTPUT,@pcount INT OUTPUT',  
                   @rcount OUTPUT,@pcount OUTPUT  
    IF @pageindex > CEILING((@rcount+0.0)/@pagesize)    --如果输入的当前页数大于实际总页数,则把实际总页数赋值给当前页数  
    BEGIN  
        SET @pageindex =  CEILING((@rcount+0.0)/@pagesize)  
    END  
    set @sql = 'select '+ @fields +' from ' + @tablename + ' w1 '  
        + ' where '+ @keys +' in ('  
            +'select top '+ ltrim(str(@pagesize)) +' ' + @keys + ' from '  
            +'('  
                +'select top ' + ltrim(STR(@pagesize * @pageindex + @beginindex)) + ' ' + @keys + ' FROM '  
            + @tablename + @new_where1 + @new_order2   
            +') w ' + @new_order1  
        +') ' + @new_order2  
    print(@sql)  
    Exec(@sql)  
    GO 

 

 

 

2. 优化后的分页过程

create PROC [dbo].[xp_GetPager_user_dt2]    
@quitdate nvarchar(10)='2015-01-01',
@userno nvarchar(10)='',
@sortfields nvarchar(100)='',
@pageindex int=1,
@pagesize int=5
AS
begin  

--构建执行脚本
declare @sql nvarchar(1800)='',
        --存储对象
        @tablename NVARCHAR(50)=' v_pn_users_fromlocal',
        --返回字段
        @returnfields nvarchar(1000)='',
        --where 条件
        @where nvarchar(200)=' where 1=1 ',--and abs([Status]) >= 10 and [Status] <> 40  and isvalid<>-1 ,
        --上次查询数量
        @lastcount int =-1  

        --计算前面查询的数据总数
        set @lastcount=(@pageindex-1)*@pagesize
        if @lastcount<0 set @lastcount=0
        --判断排序字段
        if @sortfields=''
          set @sortfields='quitdate'
          

--*******************************************返回字段设定***************************************** 
set @returnfields='code,name,fname,email,isvalid,hiredate,hirevalid,quitdate,costcenter,sex,IDCard,PassDate '
--*******************************************由条件构建Where***************************************

if @quitdate<>'2015-01-01'
   set @where+=' and quitdate  > '''+@quitdate+''''
if @userno<>''
   set @where+=' and code = '''+@userno+''''  

--*******************************************由条件构建SQL***************************************
set @sql=' 

declare @lastmaxid int=0,@total int
--缓存的临时表,并创建检索rowID
if object_id(''tempdb..#t'') is not null
    drop table #t

select row_number() over (order by '+@sortfields+') rowid, * into #t from '+@tablename

set @sql += @where

--获取按照执行排序,前面查询的数据的最大ID
set @sql +=' select top '+cast(@lastcount as nvarchar)+'  @lastmaxid=max(rowid) from #t'
set @sql+= ' group by rowid'

--获取符合条件的数据总数
set @sql+=' select @total=count(*) from #t' 

--**********************************************构造执行返回结果的SQL*****************************************
set @sql+=' select '
if @pagesize>0
   set @sql+='top '+cast(@pagesize as nvarchar) 
   set @sql+=' rowid '
   
   if @returnfields<>''
   begin
        set @sql+=','+@returnfields         
   end            
   set @sql+=' from #t
            where rowid>@lastmaxid order by rowid'

set @sql+=' select @total total,'+cast(@pagesize as nvarchar)+' pagesize,'+cast(@pageindex as nvarchar)+' pageindex'

set @sql+=' if object_id(''tempdb..#t'') is not null
    drop table #t' 
exec(@sql)  

END

 

 

效率对比

 

1. declare @pcount int,@rcount int

exec [dbo].[xp_getpager_user_dt]  

    @pcount  output,    --总页数输出  

    @rcount  output,    --总记录数输出  

    @tablename ='v_pn_users_fromlocal',    --查询表名  

    @keys ='code',        --主键  

    @fields ='code,name,fname,email,isvalid,hiredate,hirevalid,quitdate,costcenter,sex,IDCard,PassDate',    --查询字段  

    @where ='quitdate>''2015-01-01''',    --查询条件  

    @sortfields ='quitdate',    --排序字段  

    @beginindex =0,        --开始位置  

    @pageindex =1,        --当前页数  

    @pagesize =100

 

执行时间:1 min 18s

 

2. [xp_GetPager_user_dt2] @quitdate='2015-01-01',@pagesize=100

 

执行时间:<1s