广

MSSQL

  • MYSQL
  • MSSQL
  • Redis
  • MongoDB
  • oracle数据库
  • 数据管理

    sqlserver2005利用临时表和@@RowCount提高分页查询存储过程性能示例分享

    2018-05-08 11:29:09 次阅读 稿源:互联网
    零七网广告
    全网推广平台,软文发布

    最近发现现有框架的通用查询存储过程的性能慢,于是仔细研究了下代码:

    代码如下:

    Alter PROCEDURE [dbo].[AreaSelect]
        @PageSize int=0,
        @CurrentPage int=1,
        @Identifier int=NULL,
        @ParentId int=NULL,
        @AreaLevel int=NULL,
        @Children int=NULL,
        @AreaName nvarchar(50)=NULL,
        @Path nvarchar(MAX)=NULL,
        @Status int=NULL,
        @Alt int=NULL
    AS
    BEGIN
        SET NOCOUNT ON;
        IF (NOT @AreaName IS NULL)    SET @AreaName='%'+@AreaName+'%'
        IF (NOT @Path IS NULL)    SET @Path='%'+@Path+'%'
        IF (@PageSize>0)
        BEGIN
            DECLARE @TotalPage int
            Select @TotalPage=Count(Identifier) FROM Area Where
            (@Identifier IS NULL or Identifier=@Identifier)AND
            (@ParentId IS NULL or ParentId=@ParentId)AND
            (@AreaLevel IS NULL or AreaLevel=@AreaLevel)AND
            (@Children IS NULL or Children=@Children)AND
            (@AreaName IS NULL or AreaName Like @AreaName)AND
            (@Path IS NULL or Path Like @Path)AND
            (@Status IS NULL or Status=@Status)AND
            (@Alt IS NULL or Alt=@Alt)
            IF(@TotalPage%@PageSize=0)
            BEGIN
                SET @TotalPage=@TotalPage/@PageSize
            END
            ELSE
            BEGIN
                SET @TotalPage=Round(@TotalPage/@PageSize,0)+1
            END
            Select TOP (@PageSize) Identifier,ParentId,AreaLevel,Children,AreaName,Path,Status,Alt,@TotalPage as totalPage FROM Area Where
            Identifier NOT IN (Select Top (@PageSize*(@CurrentPage-1))Identifier FROM Area Where
            (@Identifier IS NULL or Identifier=@Identifier)AND
            (@ParentId IS NULL or ParentId=@ParentId)AND
            (@AreaLevel IS NULL or AreaLevel=@AreaLevel)AND
            (@Children IS NULL or Children=@Children)AND
            (@AreaName IS NULL or AreaName Like @AreaName)AND
            (@Path IS NULL or Path Like @Path)AND
            (@Status IS NULL or Status=@Status)AND
            (@Alt IS NULL or Alt=@Alt)
                order by AreaName asc)
            AND
            (@Identifier IS NULL or Identifier=@Identifier)AND
            (@ParentId IS NULL or ParentId=@ParentId)AND
            (@AreaLevel IS NULL or AreaLevel=@AreaLevel)AND
            (@Children IS NULL or Children=@Children)AND
            (@AreaName IS NULL or AreaName Like @AreaName)AND
            (@Path IS NULL or Path Like @Path)AND
            (@Status IS NULL or Status=@Status)AND
            (@Alt IS NULL or Alt=@Alt)
                order by AreaName asc
        END
        ELSE
        BEGIN
            Select Identifier,ParentId,AreaLevel,Children,AreaName,Path,Status,Alt FROM Area Where
            (@Identifier IS NULL or Identifier=@Identifier)AND
            (@ParentId IS NULL or ParentId=@ParentId)AND
            (@AreaLevel IS NULL or AreaLevel=@AreaLevel)AND
            (@Children IS NULL or Children=@Children)AND
            (@AreaName IS NULL or AreaName Like @AreaName)AND
            (@Path IS NULL or Path Like @Path)AND
            (@Status IS NULL or Status=@Status)AND
            (@Alt IS NULL or Alt=@Alt)
                order by AreaName asc
        END
    END

    发现每次查询都需要按条件查询依次Area表,性能太低,于是利用临时表将符合条件的记录取出来,然后针对临时表进行查询,代码修改如下:
    Alter PROCEDURE [dbo].[AreaSelect]
        @PageSize int=0,
        @CurrentPage int=1,
        @Identifier int=NULL,
        @ParentId int=NULL,
        @AreaLevel int=NULL,
        @Children int=NULL,
        @AreaName nvarchar(50)=NULL,
        @Path nvarchar(MAX)=NULL,
        @Status int=NULL,
        @Alt int=NULL
    AS
    BEGIN
        SET NOCOUNT ON;
        IF (NOT @AreaName IS NULL)    SET @AreaName='%'+@AreaName+'%'
        IF (NOT @Path IS NULL)    SET @Path='%'+@Path+'%'

       
        IF (@PageSize>0)
        BEGIN
            --创建临时表
            Select
            Identifier,ParentId,AreaLevel,Children,AreaName,Path,Status,Alt
            INTO #temp_Area
            FROM Area Where
            (@Identifier IS NULL or Identifier=@Identifier)AND
            (@ParentId IS NULL or ParentId=@ParentId)AND
            (@AreaLevel IS NULL or AreaLevel=@AreaLevel)AND
            (@Children IS NULL or Children=@Children)AND
            (@AreaName IS NULL or AreaName Like @AreaName)AND
            (@Path IS NULL or Path Like @Path)AND
            (@Status IS NULL or Status=@Status)AND
            (@Alt IS NULL or Alt=@Alt)
            order by AreaName asc

            DECLARE @TotalPage int
            DECLARE @SumCount int

            --取总数
            Select @SumCount=Count(Identifier) FROM #temp_Area

            IF(@SumCount%@PageSize=0)
            BEGIN
                SET @TotalPage=@SumCount/@PageSize
            END
            ELSE
            BEGIN
                SET @TotalPage=Round(@SumCount/@PageSize,0)+1
            END
            Select TOP (@PageSize) Identifier,ParentId,AreaLevel,Children,AreaName,
            Path,Status,Alt,@TotalPage as totalPage,@SumCount as SumCount
            FROM #temp_Area
            Where
            Identifier NOT IN (Select Top (@PageSize*(@CurrentPage-1))Identifier FROM #temp_Area))
        END
        ELSE
        BEGIN
            Select Identifier,ParentId,AreaLevel,Children,AreaName,Path,Status,Alt FROM Area Where
            (@Identifier IS NULL or Identifier=@Identifier)AND
            (@ParentId IS NULL or ParentId=@ParentId)AND
            (@AreaLevel IS NULL or AreaLevel=@AreaLevel)AND
            (@Children IS NULL or Children=@Children)AND
            (@AreaName IS NULL or AreaName Like @AreaName)AND
            (@Path IS NULL or Path Like @Path)AND
            (@Status IS NULL or Status=@Status)AND
            (@Alt IS NULL or Alt=@Alt)
                order by AreaName asc
        END
    END

    经过使用临时表的确提高性能,不过有发现一个问题,就是count(Identifier)的确很耗性能,于是又进行修改了

    Alter PROCEDURE [dbo].[AreaSelect]
        @PageSize int=0,
        @CurrentPage int=1,
        @Identifier int=NULL,
        @ParentId int=NULL,
        @AreaLevel int=NULL,
        @Children int=NULL,
        @AreaName nvarchar(50)=NULL,
        @Path nvarchar(MAX)=NULL,
        @Status int=NULL,
        @Alt int=NULL
    AS
    BEGIN
        SET NOCOUNT ON;
        IF (NOT @AreaName IS NULL)    SET @AreaName='%'+@AreaName+'%'
        IF (NOT @Path IS NULL)    SET @Path='%'+@Path+'%'

       
        IF (@PageSize>0)
        BEGIN
            --创建中记录数
            DECLARE @SumCount int

            --创建临时表
            Select
            Identifier,ParentId,AreaLevel,Children,AreaName,Path,Status,Alt
            INTO #temp_Area
            FROM Area Where
            (@Identifier IS NULL or Identifier=@Identifier)AND
            (@ParentId IS NULL or ParentId=@ParentId)AND
            (@AreaLevel IS NULL or AreaLevel=@AreaLevel)AND
            (@Children IS NULL or Children=@Children)AND
            (@AreaName IS NULL or AreaName Like @AreaName)AND
            (@Path IS NULL or Path Like @Path)AND
            (@Status IS NULL or Status=@Status)AND
            (@Alt IS NULL or Alt=@Alt)
            order by AreaName asc
            --设置总记录数为刚操作的记录数
            SET @SumCount=@@RowCount

            DECLARE @TotalPage int

            IF(@SumCount%@PageSize=0)
            BEGIN
                SET @TotalPage=@SumCount/@PageSize
            END
            ELSE
            BEGIN
                SET @TotalPage=Round(@SumCount/@PageSize,0)+1
            END
            Select TOP (@PageSize) Identifier,ParentId,AreaLevel,Children,AreaName,
            Path,Status,Alt,@TotalPage as totalPage,@SumCount as SumCount
            FROM #temp_Area
            Where
            Identifier NOT IN (Select Top (@PageSize*(@CurrentPage-1))Identifier FROM #temp_Area))
        END
        ELSE
        BEGIN

            Select Identifier,ParentId,AreaLevel,Children,AreaName,Path,Status,Alt FROM Area Where
            (@Identifier IS NULL or Identifier=@Identifier)AND
            (@ParentId IS NULL or ParentId=@ParentId)AND
            (@AreaLevel IS NULL or AreaLevel=@AreaLevel)AND
            (@Children IS NULL or Children=@Children)AND
            (@AreaName IS NULL or AreaName Like @AreaName)AND
            (@Path IS NULL or Path Like @Path)AND
            (@Status IS NULL or Status=@Status)AND
            (@Alt IS NULL or Alt=@Alt)
            order by AreaName asc
        END
    END

    零七网部分新闻及文章转载自互联网,供读者交流和学习,若有涉及作者版权等问题请及时与我们联系,以便更正、删除或按规定办理。感谢所有提供资讯的网站,欢迎各类媒体与零七网进行文章共享合作。

    零七网广告
    零七网广告
    零七网广告
    零七网广告