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

  • 相关阅读:
    IsCallback和IsPostBack的区别
    win7 无Internet访问权限的解决方法
    Microsoft Office 2007的ContentType
    浏览器渲染原理
    css中hideFocus的用法
    js实现小球碰撞(数学之美)
    从浏览器的渲染原理讲CSS性能
    Jquery 常用方法经典总结
    web前端开发必备压缩工具整理
    15个精美PC/手机端自响应网页设计案例与欣赏
  • 原文地址:https://www.cnblogs.com/mikel/p/1403560.html
Copyright © 2011-2022 走看看