zoukankan      html  css  js  c++  java
  • SQL Server 2005中利用临时表和@@RowCount提高分页查询存储过程性能

    最近发现现有框架的通用查询存储过程的性能慢,于是仔细研究了下代码:
    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

    我的blog

    KiWing框架


    作者:mikel
    出处:http://www.cnblogs.com/mikel/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
    该文章也同时发布在我的独立博客中-www.mikel.cn

  • 相关阅读:
    几种常用的曲线
    0188. Best Time to Buy and Sell Stock IV (H)
    0074. Search a 2D Matrix (M)
    0189. Rotate Array (E)
    0148. Sort List (M)
    0859. Buddy Strings (E)
    0316. Remove Duplicate Letters (M)
    0452. Minimum Number of Arrows to Burst Balloons (M)
    0449. Serialize and Deserialize BST (M)
    0704. Binary Search (E)
  • 原文地址:https://www.cnblogs.com/mikel/p/1403560.html
Copyright © 2011-2022 走看看