sqlserver2005利用临时表和@@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

(0)

相关推荐

  • oracle,mysql,SqlServer三种数据库的分页查询的实例

    MySql: MySQL数据库实现分页比较简单,提供了 LIMIT函数.一般只需要直接写到sql语句后面就行了.LIMIT子 句可以用来限制由SELECT语句返回过来的数据数量,它有一个或两个参数,如果给出两个参数, 第一个参数指定返回的第一行在所有数据中的位置,从0开始(注意不是1),第二个参数指定最多返回行数.例如:select * from table WHERE - LIMIT 10; #返回前10行select * from table WHERE - LIMIT 0,10; #返回前

  • sqlserver分页查询处理方法小结

    sqlserver2008不支持关键字limit ,所以它的分页sql查询语句将不能用MySQL的方式进行,幸好sqlserver2008提供了top,rownumber等关键字,这样就能通过这几个关键字实现分页. 下面是本人在网上查阅到的几种查询脚本的写法: 几种sqlserver2008高效分页sql查询语句 top方案: sql code: select top 10 * from table1 where id not in(select top 开始的位置 id from table1

  • 真正高效的SQLSERVER分页查询(多种方案)

    Sqlserver数据库分页查询一直是Sqlserver的短板,闲来无事,想出几种方法,假设有表ARTICLE,字段ID.YEAR...(其他省略),数据53210条(客户真实数据,量不大),分页查询每页30条,查询第1500页(即第45001-45030条数据),字段ID聚集索引,YEAR无索引,Sqlserver版本:2008R2 第一种方案.最简单.普通的方法: 复制代码 代码如下: SELECT TOP 30 * FROM ARTICLE WHERE ID NOT IN(SELECT T

  • 高效的SQLSERVER分页查询(推荐)

    第一种方案.最简单.普通的方法: 复制代码 代码如下: SELECT TOP 30 * FROM ARTICLE WHERE ID NOT IN(SELECT TOP 45000 ID FROM ARTICLE ORDER BY YEAR DESC, ID DESC) ORDER BY YEAR DESC,ID DESC 平均查询100次所需时间:45s 第二种方案: 复制代码 代码如下: SELECT * FROM ( SELECT TOP 30 * FROM (SELECT TOP 4503

  • 详解SQLServer和Oracle的分页查询

    不管是DRP中的分页查询代码的实现还是面试题中看到的关于分页查询的考察,都给我一个提示:分页查询是重要的.当数据量大的时候是必须考虑的.之前一直没有花时间停下来好好总结这里.现在又将Oracle视频中关于分页查询的内容看了一遍,发现很容易就懂了. 1.分页算法     最开始我在网上查找资料的时候,看到很多分页内容,感觉很多很乱.其实不是这样.网上那些资料大同小异.问题出在了我自己这里.我没搞明白进行分页的前提是什么?我们都知道只要有分页都会涉及这些变量:每页又多少条记录(pageSize).当

  • SQLSERVER分页查询关于使用Top方式和row_number()解析函数的不同

    临近春节,心早已飞了不在工作上了,下面小编给大家整理些数据库的几种分页查询. Sql Sever 2005之前版本: select top 页大小 * from 表名 where id not in ( select top 页大小*(查询第几页-1) id from 表名 order by id ) order by id 例如: select top 10 * --10 为页大小 from [TCCLine].[dbo].[CLine_CommonImage] where id not in

  • sqlserver关于分页存储过程的优化【让数据库按我们的意思执行查询计划】

    复制代码 代码如下: --代码一DECLARE @cc INT SELECT NewsId,ROW_NUMBER() OVER(ORDER BY SortNum DESC) AS RowIndex INTO #tb FROM news WITH(NOLOCK) WHERE NewsTypeId=@NewsTypeId AND IsShow=1 SET @cc = @@ROWCOUNT SELECT n.* FROM news AS n WITH(NOLOCK), #tb As t WHERE t

  • sqlserver2005利用临时表和@@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, 

  • ADO调用分页查询存储过程的实例讲解

    一.分页存储过程 ----------使用存储过程编写一个分页查询----------------------- set nocount off --关闭SqlServer消息 --set nocount on --开启SqlServer消息 go create proc usp_getMyStudentsDataByPage --输入参数 @pagesize int=7,--每页记录条数 @pageindex int=1,--当前要查看第几页的记录 --输出参数 @recordcount in

  • mybatis-plus分页查询的实现示例

    按照官方文档进行的配置:快速开始|mybatis-plus 引入依赖: <!-- 引入mybatisPlus --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.2.0</version> </dependency> <!--

  • MyBatis Plus 实现多表分页查询功能的示例代码

    在Mybatis Plus 中,虽然IService 接口帮我们定义了很多常用的方法,但这些都是 T 对象有用,如果涉及到 多表的查询,还是需要自定义Vo 对象和自己编写sql 语句,Mybatis Plus提供了一个Page 对象,查询是需要设置其中的 size 字段 和 current 字段的值 一.分页配置 可以直接使用selectPage这样的分页,但返回的数据确实是分页后的数据,但在控制台打印的SQL语句其实并没有真正的物理分页,而是通过缓存来获得全部数据中再进行的分页,这样对于大数据

  • C# winform分页查询的实现示例

    1.功能需求 本实例将通过c# winform实现简单的分页功能,需要的基础知识有SQL语句,c#语言基础以及c# winform的一些简单知识. 2.界面设计 这是一个简单的分页查询的界面,可以输入任意字段进行查询,这四个字段在数据准备会提到,整体界面如图1所示. 图1 中间显示是一个DataGridView,编辑好列和id,SortMode选择Automatic,意思是所有列自动铺满DataGridView,如图2所示. 图2 3.数据准备 本实例涉及到删查改,因此要有数据表以及对数据表进行

  • MyBatis-Plus 分页查询的实现示例

    方法: 使用selectPage()方法,第一个参数是传入分页方法(传入当前页和当前显示多少条数据),第二个参数是传入查询条件(如果查询全部的话,可以传null). 前提: 表中的数据为: 第一种方式: //分页查询 Page<Employee> employees = employeeMapper.selectPage(new Page<>(3, 2), null); System.out.println("数据为:"+employees.getRecords

  • SQL分页查询存储过程代码分享

    话不多说,请看代码 ------------------------------------- -----作者:张欣宇 -----时间:2013-06-28 -----简介:根据参数和条件分页查询 ------------------------------------- Create proc [dbo].[Up_PagingQueryByParameter] ( ----- 表名或能查询到结果的SQL语句{SQL语句左右必须有括号例:(select * from tbl1)} @TableN

  • SQL Server 分页查询存储过程代码

    复制代码 代码如下: CREATE PROCEDURE [dbo].[up_Pager] @table varchar(2000), --表名 @col varchar(50), --按该列来进行分页 @orderby bit, --排序,0-顺序,1-倒序 @collist varchar(800),--要查询出的字段列表,*表示全部字段 @pagesize int, --每页记录数 @page int, --指定页 @condition varchar(800) --查询条件 AS DECL

  • 利用JQuery和Servlet实现跨域提交请求示例分享

    原理:JavaScript的Ajax不可以跨域,但是可以通过向本地的一个Servlet发出请求,由Servlet完成跨域.再把远程的结构返回给客户端.这样Ajax就可以跨域了.在后面,再发一个PHP版本的,请大家关注啊.下面是代码 JS代码: 注意:在Post方式时,param1和param2为向远程发送的参数值,可以有多个. 复制代码 代码如下: //GET方式function reqeustCrossDomainProxyGet(){    var url = "http://www.bai

  • JDBC使用游标实现分页查询的方法

    本文实例讲述了JDBC使用游标实现分页查询的方法.分享给大家供大家参考,具体如下: /** * 一次只从数据库中查询最大maxCount条记录 * @param sql 传入的sql语句 * @param startNo 从哪一条记录开始 * @param maxCount 总共取多少条记录 */ public void getData(String sql,int startNo,int maxCount){ Connection conn = ConnectionUtil.getConnec

随机推荐