通用分页存储过程

1、 目的

1.1 提高现在的分页存储过程性能,给所有分页存储过程提供一个标准的调用接口。

2、 两个存储结构性能分析对比

一、 原有通用分页存储过程

大体写法格式 分六个部分

输出字段列表

整理列出需要输出字段

例:

SET @FieldList = '

PersonID,

  PersonNameID,

  SkillPKId,

  SkillName,

  StartDate,

  EndDate,

  AuthoriseOrganization,

OriginalFile '

数据检索来源

指定检索的数据源

例:

SET @FromClause  =  ' VW_HR_PERSON_SKILL '

检索条件子句

给出检索过滤条件

例:

' PersonID IN

(SELECT RightContributor

FROM HR_RESOURCE_RIGHT

WITH (NOLOCK)

WHERE RightOwner = ''' + @personId + ''' AND

      ContributorType = 1 AND

      ViewPersonUnitInfo = 1 ' + 

') '

完整检索SQL语句

拼装完整的SQL语句

例:

SET @basicSQL = ' SELECT '+@FieldList+ ' FROM '  + @FromClause  + ' WITH (NOLOCK) WHERE ' + @WhereClause

在页面需要统计总行数时

需要COUNT 一次,输出总行数,作为返回值。

执行分页输出数据

根据分页排序要求,用嵌套子查询方法,先将整个数据集正序排序检索的到指定页以前所有行数(TOP到当前页行所有行数),再倒序排序检索指定需要的行数(TOP需要的行数),最后按指定的排序要求输出数据。

例:

EXEC ('SELECT * FROM (SELECT TOP ' + @PageCount + ' * FROM (SELECT TOP ' + @Pages + ' * FROM (' + @basicSQL + ') A ORDER BY PersonID ASC, StartDate DESC ) B ORDER BY PersonID DESC, StartDate ASC) C ORDER BY PersonID ASC, StartDate DESC ' )

总结分析问题:

这里为了得到所要的数据,检索进行了三次子查询,可以肯定的会影响性能。

8  原存储过程示例:

/*###############组装数据检索SQL语句开始###############*/

DECLARE @basicSQL VARCHAR(8000)

IF @WhereClause = ''

BEGIN

SET @basicSQL = ' SELECT '+@FieldList+ ' FROM '  + @FromClause + ' WITH (NOLOCK) '

END

ELSE

BEGIN

SET @basicSQL = ' SELECT '+@FieldList+ ' FROM '  + @FromClause + ' WITH (NOLOCK) '+' WHERE ' + @WhereClause  

END

--PRINT @basicSQL

--求记录总数

DECLARE @strSql VARCHAR(3000)

IF @totalNum=-1

BEGIN

CREATE TABLE #temp1(num INT)

INSERT #temp1 VALUES(0)

SET @strSql = 'SELECT @temp1 = COUNT(*)  FROM (' + @basicSQL + ') A'

SET  @strSql='DECLARE @temp1 INT ' +@strSql+'  UPDATE #temp1 SET num=@temp1 '

--PRINT (@strSql)

EXEC (@strSql)

SELECT @totalNum=(SELECT * FROM #temp1)

DROP TABLE #temp1

END

/*###############组装数据检索SQL语句结束###############*/

EXEC ('SELECT * FROM (SELECT TOP ' + @PageCount + ' * FROM (' + @basicSQL + ') A ORDER BY ' + @OrderClause + '  ) B ORDER BY ' + @OrderClause + ' desc '  )

 

二、 新的分页存储过程

新的分页存储过程利用SQL2005的新特性RowNumber 函数

大体写法格式 分六个部分

输出字段列表

这个部分要指定新特性RowNumber 函数,在RowNumber 函数指定排序字段、排序方法以及另名。

例:

SET @FieldList = '

ROW_NUMBER() OVER(ORDER BY CustomerPKId  DESC) AS RowIndex,

CustomerPKId,

CustomerName,

WebSite,

ProvinceCityName,

SaleRepresentNameId,

ServicePersonNameId,

CreateDateTime,

EditLock

数据检索来源

指定检索的数据源

例:

SET @FromClause  =  ' VW_CUS_CUSTOMER '

检索条件子句

给出检索过滤条件

例:

SET @WhereClause=

' PersonID IN

(SELECT RightContributor

FROM HR_RESOURCE_RIGHT

WITH (NOLOCK)

WHERE RightOwner = ''' + @personId + ''' AND

      ContributorType = 1 AND

      ViewPersonUnitInfo = 1 ' + 

') '

完整检索SQL语句

拼装完整的SQL语句,在这个过程中就要多加上RowNumber函数的范围行数

例:

SET @basicSQL = '

SELECT * FROM (

SELECT '+@FieldList+ ' FROM '  + @FromClause  + ' WITH (NOLOCK)   WHERE ' + @WhereClause+

) A

' WHERE  RowIndex BETWEEN '  +

        CONVERT(VARCHAR, ( @CurrentPageNo - 1 ) * @PerPageCount + 1)  +

     ' AND ' + CONVERT(VARCHAR, @CurrentPageNo * @PerPageCount)

在页面需要统计总行数时

需要COUNT 一次,输出总行数,作为返回值。

分析问题总结:

1) 在用新的分页存储过程中检索所需要的页数时只对RowNumber函数行取出所需要的行数就行,可以省去几次子查询。

2) 把新的存储过程改进后,可以做成一个标准存储过程,以后分页存储过程都可以通过调用这个标准的存储过程。

 

三、 两个分页存储过程在相同数据情况下的执行性能对比

a) 使用没有索引对比表数据

三次平均值

1万条记录执行时间

表中实际6,157条记录中查询100条记录       

1-10万条记录执行时间(MS

表中实际567,604条记录中查询100条记录    

10万条以上记录执行时间(MS

表中实际15,841,860 条记录中查询100条记录

原来

存储过程

ms(70)

00:00:10-- ms(10423)

00:04:34 -- ms(266776)

存储过程

ms(33)

00:00:01- ms(1063)

00:00:46 -- ms(46700)

b) 使用索引对比表数据

三次平均值

1万条记录执行时间

表中实际6,157条记录中查询100条记录       

1-10万条记录执行时间(MS

表中实际567,604条记录中查询100条记录    

10万条以上记录执行时间(MS

表中实际15,841,860 条记录中查询100条记录

原来

存储过程

ms(66)

ms(16)

 ms(86)

存储过程

ms(8)

ms(13)

ms(45)

四、 结论

a) 新的方法存储过程可以做成一个标准的存储过程,供其他地方统一调用,简单方便。

b) 在测试的性能上有比较大的提高。

 

五、 标准通用分页存储过程

1 标准通用分页存储过程原形。

CREATE PROCEDURE [dbo].[COMMON_PROCEDURE_SelectWithPage]

     @Sql VARCHAR(8000),

     @CurrentPageNo INT,

     @PerPageCount INT,

     @TotalNum INT OUTPUT

AS 

SET NOCOUNT ON --阻止在结果集中返回可显示受Transact-SQL

语句或存储过程影响的行计数的消息,ON 时,不返回计数

    DECLARE @SqlCmd NVARCHAR(4000)

------------------------------------------

--查询数据

    SET @SqlCmd = 'SELECT * FROM (' + @Sql + ') A WHERE RowIndex BETWEEN

        + CONVERT(VARCHAR, ( @CurrentPageNo - 1 ) * @PerPageCount + 1)

        + ' AND ' + CONVERT(VARCHAR, @CurrentPageNo * @PerPageCount) 

    EXEC sp_executesql @SqlCmd --执行Transact-SQL语句

------------------------------------------

--求记录总数

    IF @TotalNum = -1

     BEGIN

            CREATE TABLE #Temp1 ( num INT )  

            INSERT  INTO #Temp1

            EXEC ( 'SELECT count(*) FROM (' + @Sql + ') A')

            SELECT  @TotalNum = ( SELECT  *  FROM  #Temp1 )  

            DROP TABLE #Temp1  

END

 

2 调用示例

SET @basicSQL = 'SELECTROW_NUMBER() OVER(ORDER BY CreateDateTime DESC) AS RowIndex,

CdmuExperiencePKId,

ExperiencePKId,

MemberPKId,

LoginAccount,

CustomerPKId,

CustomerName,

ShopState,

ExperienceClass,

ProcessSatae,

EndDate,

EmployeePKId,

EmployeeNameId,

DemandDate

FROMdbo.VW_BIZ_SHOP_MAIN 

WHEREAgentMemberPKId = '

+ CONVERT(VARCHAR, @AgentMemberPKId)

EXEC dbo.COMMON_PROCEDURE_SelectWithPage

@basicSQL, --  varchar(8000)

@CurrentPageNo, --  int

@PerPageCount, --  int

@TotalNum OUTPUT


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值