• 分页存储过程效率对比


    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

  • 相关阅读:
    mybatis中的#和$的区别
    spring ioc三种注入方式
    JSP中动态INCLUDE与静态INCLUDE的区别
    j2ee部分
    面试 框架部分
    注册Jdbc驱动程序的三种方式
    union和union all有什么不同?
    面试 JavaWeb 部分
    Cordova插件开发(iOS/Android)--看这篇就够了
    程序员,请不要只看技术
  • 原文地址:https://www.cnblogs.com/jeffry/p/4812475.html
Copyright © 2020-2023  润新知