`

net/sqlserver2000百万数据分页研究

阅读更多
公司一项目数据达到上百万,普通的分页方式满足不了要求,经常发生超时的错误,所以有必要对分页的方式来做下研究。

经过搜集和测试,当前网上的成熟的分页方式有以下几种方案:

分页存储过程1. 以下为引用的内容:
/*
说明:适合单表查询 cn-web.com提供
*/

CREATE PROCEDURE p_qcd_Pagination 

@tblName   varchar(255),       -- 表名 

@strGetFields varchar(1000) = '*',  -- 需要返回的列 

@fldName varchar(255)='',      -- 排序的字段名 

@PageSize   int = 10,          -- 页尺寸 

@PageIndex  int = 1,           -- 页码 

@doCount  bit = 0,   -- 返回记录总数, 非 0 值则返回 

@OrderType bit = 0,  -- 设置排序类型, 非 0 值则降序 

@strWhere  varchar(1500) = ''  -- 查询条件 (注意: 不要加 where) 

AS 

declare @strSQL   varchar(5000)       -- 主语句 

declare @strTmp   varchar(110)        -- 临时变量 

declare @strOrder varchar(400)        -- 排序类型 



if @doCount != 0 

begin 

   if @strWhere !='' 

   set @strSQL = 'select count(*) as Total from ['+ @tblName +'] where '+ @strWhere 

   else 

   set @strSQL = 'select count(*) as Total from ['+ @tblName +']'

end 

--以上代码的意思是如果@doCount传递过来的不是0,就执行总数统计。以下的所有代码都
--是@doCount为0的情况 

else 

begin 



if @OrderType != 0 

begin 

   set @strTmp = '<(select min' 

set @strOrder = ' order by ['+ @fldName +'] desc'

--如果@OrderType不是0,就执行降序,这句很重要! 

end 

else 

begin 

   set @strTmp = '>(select max'

   set @strOrder = ' order by ['+ @fldName +'] asc'

end 



if @PageIndex = 1 

begin 

   if @strWhere != ''   

    set @strSQL = 'select top ' + str(@PageSize) +' '+@strGetFields+ '  from ['+ @tblName +'] where ' + @strWhere + ' ' + @strOrder 

    else 

    set @strSQL = 'select top ' + str(@PageSize) +' '+@strGetFields+ '  from ['+ @tblName +'] '+ @strOrder 

--如果是第一页就执行以上代码,这样会加快执行速度 

end 

else 

begin 

--以下代码赋予了@strSQL以真正执行的SQL代码 

set @strSQL = 'select top ' + str(@PageSize) +' '+@strGetFields+ '  from [' + @tblName +'] where [' + @fldName + ']' + @strTmp + '(['+ @fldName + ']) 
from (select top ' + str((@PageIndex-1)*@PageSize) + ' ['+ @fldName + '] from ['+ @tblName +']' + @strOrder + ') as tblTmp)'+ @strOrder 



if @strWhere != '' 

   set @strSQL = 'select top ' + str(@PageSize) +' '+@strGetFields+ '  from ['+ @tblName +'] where [' + @fldName + ']' + @strTmp + '(['+ @fldName + ']) from (select top ' + str((@PageIndex-1)*@PageSize) + ' ['+ @fldName + '] 
from ['+ @tblName +'] where ' + @strWhere + ' ' + @strOrder + ') as tblTmp) and ' + @strWhere + ' ' + @strOrder 

end 

end   

exec ( @strSQL)
GO




此方案只适合单表,中小数据查询,当条件出现in(1,2,3,4,5……)时,则速度明显下降。

分页存储过程2

以下为引用的内容:
create PROCEDURE p_qcd_PaginationDichotomy
  (
  @tblName     nvarchar(200),        ----要显示的表或多个表的连接
  @fldName     nvarchar(500) = '*',    ----要显示的字段列表
  @pageSize    int = 10,        ----每页显示的记录个数
@page        int = 1,        ----要显示那一页的记录
@fldSort    nvarchar(200) = null,    ----排序字段列表或条件
@Sort        bit = 0,        ----排序方法,0为升序,1为降序(如果是多字段排列Sort指代最后一个排序字段的排列顺序(最后一个排序字段不加排序标记)--程序传参如:' SortA Asc,SortB Desc,SortC ')
@strCondition    nvarchar(1000) = null,    ----查询条件,不需where
@ID        nvarchar(150),        ----主表的主键
@Dist                 bit = 0,           ----是否添加查询字段的 DISTINCT 默认0不添加/1添加
@pageCount    int = 1 output,            ----查询结果分页后的总页数
@Counts    int = 1 output                ----查询到的记录数
)
AS
SET NOCOUNT ON
Declare @sqlTmp nvarchar(1000)        ----存放动态生成的SQL语句
Declare @strTmp nvarchar(1000)        ----存放取得查询结果总数的查询语句
Declare @strID     nvarchar(1000)        ----存放取得查询开头或结尾ID的查询语句

Declare @strSortType nvarchar(10)    ----数据排序规则A
Declare @strFSortType nvarchar(10)    ----数据排序规则B

Declare @SqlSelect nvarchar(50)         ----对含有DISTINCT的查询进行SQL构造
Declare @SqlCounts nvarchar(50)          ----对含有DISTINCT的总数查询进行SQL构造

declare @timediff datetime  --耗时测试时间差
select @timediff=getdate()

if @Dist  = 0
begin
     set @SqlSelect = 'select '
     set @SqlCounts = 'Count(*)'
end
else
begin
     set @SqlSelect = 'select distinct '
     set @SqlCounts = 'Count(DISTINCT '+@ID+')'
end


if @Sort=0
begin
     set @strFSortType=' ASC '
     set @strSortType=' DESC '
end
else
begin
     set @strFSortType=' DESC '
     set @strSortType=' ASC '
end



--------生成查询语句cn-web.com提供--------
--此处@strTmp为取得查询结果数量的语句
if @strCondition is null or @strCondition=''     --没有设置显示条件
begin
     set @sqlTmp =  @fldName + ' From ' + @tblName
     set @strTmp = @SqlSelect+' @Counts='+@SqlCounts+' FROM '+@tblName
     set @strID = ' From ' + @tblName
end
else
begin
     set @sqlTmp = + @fldName + 'From ' + @tblName + ' where (1>0) ' + @strCondition
     set @strTmp = @SqlSelect+' @Counts='+@SqlCounts+' FROM '+@tblName + ' where (1>0) ' + @strCondition
     set @strID = ' From ' + @tblName + ' where (1>0) ' + @strCondition
end

----取得查询结果总数量-----
exec sp_executesql @strTmp,N'@Counts int out ',@Counts out
declare @tmpCounts int
if @Counts = 0
     set @tmpCounts = 1
else
     set @tmpCounts = @Counts

     --取得分页总数
     set @pageCount=(@tmpCounts+@pageSize-1)/@pageSize

     /**//**//**//**当前页大于总页数 取最后一页**/
     if @page>@pageCount
         set @page=@pageCount

     --/*-----数据分页2分处理-------*/
     declare @pageIndex int --总数/页大小
     declare @lastcount int --总数%页大小 

     set @pageIndex = @tmpCounts/@pageSize
     set @lastcount = @tmpCounts%@pageSize
     if @lastcount > 0
         set @pageIndex = @pageIndex + 1
     else
         set @lastcount = @pagesize

    --//***显示分页
    if @strCondition is null or @strCondition=''     --没有设置显示条件
    begin
        if @pageIndex<2 or @page<=@pageIndex / 2 + @pageIndex % 2   --前半部分数据处理
            begin 
                if @page=1
                    set @strTmp=@SqlSelect+' top '+ CAST(@pageSize as VARCHAR(4))+' '+ @fldName+' from '+@tblName                        
                        +' order by '+ @fldSort +' '+ @strFSortType
                else
                begin
                    if @Sort=1
                    begin                    
                    set @strTmp=@SqlSelect+' top '+ CAST(@pageSize as VARCHAR(4))+' '+ @fldName+' from '+@tblName
                        +' where '+@ID+' <(select min('+ @ID +') from ('+ @SqlSelect+' top '+ CAST(@pageSize*(@page-1) as Varchar(20)) +' '+ @ID +' from '+@tblName
                        +' order by '+ @fldSort +' '+ @strFSortType+') AS TBMinID)'
                        +' order by '+ @fldSort +' '+ @strFSortType
                    end
                    else
                    begin
                    set @strTmp=@SqlSelect+' top '+ CAST(@pageSize as VARCHAR(4))+' '+ @fldName+' from '+@tblName
                        +' where '+@ID+' >(select max('+ @ID +') from ('+ @SqlSelect+' top '+ CAST(@pageSize*(@page-1) as Varchar(20)) +' '+ @ID +' from '+@tblName
                        +' order by '+ @fldSort +' '+ @strFSortType+') AS TBMinID)'
                        +' order by '+ @fldSort +' '+ @strFSortType 
                    end
                end    
            end
        else
            begin
            set @page = @pageIndex-@page+1 --后半部分数据处理
                if @page <= 1 --最后一页数据显示                
                    set @strTmp=@SqlSelect+' * from ('+@SqlSelect+' top '+ CAST(@lastcount as VARCHAR(4))+' '+ @fldName+' from '+@tblName
                        +' order by '+ @fldSort +' '+ @strSortType+') AS TempTB'+' order by '+ @fldSort +' '+ @strFSortType 
                else
                    if @Sort=1
                    begin
                    set @strTmp=@SqlSelect+' * from ('+@SqlSelect+' top '+ CAST(@pageSize as VARCHAR(4))+' '+ @fldName+' from '+@tblName
                        +' where '+@ID+' >(select max('+ @ID +') from('+ @SqlSelect+' top '+ CAST(@pageSize*(@page-2)+@lastcount as Varchar(20)) +' '+ @ID +' from '+@tblName
                        +' order by '+ @fldSort +' '+ @strSortType+') AS TBMaxID)'
                        +' order by '+ @fldSort +' '+ @strSortType+') AS TempTB'+' order by '+ @fldSort +' '+ @strFSortType
                    end
                    else
                    begin
                    set @strTmp=@SqlSelect+' * from ('+@SqlSelect+' top '+ CAST(@pageSize as VARCHAR(4))+' '+ @fldName+' from '+@tblName
                        +' where '+@ID+' <(select min('+ @ID +') from('+ @SqlSelect+' top '+ CAST(@pageSize*(@page-2)+@lastcount as Varchar(20)) +' '+ @ID +' from '+@tblName
                        +' order by '+ @fldSort +' '+ @strSortType+') AS TBMaxID)'
                        +' order by '+ @fldSort +' '+ @strSortType+') AS TempTB'+' order by '+ @fldSort +' '+ @strFSortType 
                    end
            end
    end =@pageIndex / 2 + @pageIndex % 2   --前半部分数据处理
        begin
                if @page=1
                    set @strTmp=@SqlSelect+' top '+ CAST(@pageSize as VARCHAR(4))+' '+ @fldName+' from '+@tblName                        
                        +' where 1=1 ' + @strCondition + ' order by '+ @fldSort +' '+ @strFSortType
                else if(@Sort=1)
                begin                    
                    set @strTmp=@SqlSelect+' top '+ CAST(@pageSize as VARCHAR(4))+' '+ @fldName+' from '+@tblName
                        +' where '+@ID+' <(select min('+ @ID +') from ('+ @SqlSelect+' top '+ CAST(@pageSize*(@page-1) as Varchar(20)) +' '+ @ID +' from '+@tblName
                        +' where (1=1) ' + @strCondition +' order by '+ @fldSort +' '+ @strFSortType+') AS TBMinID)'
                        +' '+ @strCondition +' order by '+ @fldSort +' '+ @strFSortType
                end
                else
                begin
                    set @strTmp=@SqlSelect+' top '+ CAST(@pageSize as VARCHAR(4))+' '+ @fldName+' from '+@tblName
                        +' where '+@ID+' >(select max('+ @ID +') from ('+ @SqlSelect+' top '+ CAST(@pageSize*(@page-1) as Varchar(20)) +' '+ @ID +' from '+@tblName
                        +' where (1=1) ' + @strCondition +' order by '+ @fldSort +' '+ @strFSortType+') AS TBMinID)'
                        +' '+ @strCondition +' order by '+ @fldSort +' '+ @strFSortType 
                end           
        end
        else
        begin 
            set @page = @pageIndex-@page+1 --后半部分数据处理
            if @page <= 1 --最后一页数据显示
                    set @strTmp=@SqlSelect+' * from ('+@SqlSelect+' top '+ CAST(@lastcount as VARCHAR(4))+' '+ @fldName+' from '+@tblName
                        +' where (1=1) '+ @strCondition +' order by '+ @fldSort +' '+ @strSortType+') AS TempTB'+' order by '+ @fldSort +' '+ @strFSortType                     
            else if(@Sort=1)
                    set @strTmp=@SqlSelect+' * from ('+@SqlSelect+' top '+ CAST(@pageSize as VARCHAR(4))+' '+ @fldName+' from '+@tblName
                        +' where '+@ID+' >(select max('+ @ID +') from('+ @SqlSelect+' top '+ CAST(@pageSize*(@page-2)+@lastcount as Varchar(20)) +' '+ @ID +' from '+@tblName
                        +' where (1=1) '+ @strCondition +' order by '+ @fldSort +' '+ @strSortType+') AS TBMaxID)'
                        +' '+ @strCondition+' order by '+ @fldSort +' '+ @strSortType+') AS TempTB'+' order by '+ @fldSort +' '+ @strFSortType    
            else
                    set @strTmp=@SqlSelect+' * from ('+@SqlSelect+' top '+ CAST(@pageSize as VARCHAR(4))+' '+ @fldName+' from '+@tblName
                        +' where '+@ID+' <(select min('+ @ID +') from('+ @SqlSelect+' top '+ CAST(@pageSize*(@page-2)+@lastcount as Varchar(20)) +' '+ @ID +' from '+@tblName
                        +' where (1=1) '+ @strCondition +' order by '+ @fldSort +' '+ @strSortType+') AS TBMaxID)'
                        +' '+ @strCondition+' order by '+ @fldSort +' '+ @strSortType+') AS TempTB'+' order by '+ @fldSort +' '+ @strFSortType            
        end    
    end

    else --有查询条件
    begin
        if @pageIndex<2 or @page<

------返回查询结果-----
--select @pageCount ,@Counts
--select @pageCount  
exec sp_executesql @strTmp
select datediff(ms,@timediff,getdate()) as 耗时
--print @strTmp
SET NOCOUNT OFF
GO




此分页俗称二分法,执行效率超快,数据量达到百万后效率也没有明显下降,缺点同上,当条件出现in(1,2,3,4,5……)时,则速度明显下降。

分页存储过程3

以下为引用的内容:
CREATE procedure p_qcd_Paginationcursor
@sql nvarchar(4000), --要执行的sql语句
@currentpage int=1, --要显示的页码
@pagesize int=10, --每页的大小
@pagecount int=0 out, --总页数
@recordCount int=0 out--总记录数
as
set nocount on
declare @cursor int --cursor 是游标的id

declare @timediff datetime  --耗时测试时间差 cn-web.com提供
select @timediff=getdate()

exec sp_cursoropen @cursor output,@sql,@scrollopt=1,@ccopt=1,@rowcount=@pagecount output
select @recordCount=@pagecount
select @pagecount=ceiling(1.0*@pagecount/@pagesize) ,@currentpage=(@currentpage-1)*@pagesize+1
select @pagecount,@currentpage
exec sp_cursorfetch @cursor ,16,@currentpage,@pagesize
exec sp_cursorclose @cursor
select datediff(ms,@timediff,getdate()) as 耗时
GO




此方案所说是微软没有公开的游标分页,刚开始怀疑游标分页肯定浪费性能,不过经过详细测试后,发现微软就是微软,不管如何测试,不管条件如何复杂,数据量再大,性能一直保持最强劲。

总结:在没有in(1,2,3,4,5……)之类的条件的查询时,三种方案的性能:方案3=方案2>方案1。当存在复杂条件时,方案3>方案2=方案1。
分享到:
评论

相关推荐

    sqlserver 存储过程分页(支持千万级)算法研究

    本文将深入探讨SQL Server存储过程中的高级分页技术,特别是针对千万级别数据量的场景,通过分析提供的代码示例,提炼出核心知识点,帮助读者理解和掌握高效分页查询的实现方法。 ### 1. 使用临时表和ROWCOUNT实现...

    SSH框架+SQLServer实现分页的小项目

    通过研究这个项目,开发者可以学习到SSH框架的整合、Spring的bean管理和事务处理、Hibernate的数据库操作,以及SQLServer的分页查询技巧。同时,对于提高Web应用的用户体验,理解分页原理和实现方式也是必不可少的。

    jsp的分页,jsp+sqlserver源码

    本资源提供了基于JSP(JavaServer Pages)和SQL Server数据库的分页实现源码,适合对这方面感兴趣或者正在开发类似功能的开发者参考。 JSP是一种服务器端脚本语言,用于创建动态Web页面。它结合了HTML、Java代码和...

    sqlserver2000的northwind数据库

    【SQL Server 2000的Northwind...通过深入研究和实践Northwind数据库,不仅能够掌握SQL Server 2000的基本操作,还能进一步提升数据库设计、查询优化、安全管理等方面的能力,为后续的数据库管理工作打下坚实的基础。

    LINQ To SQL实现分页效果源码

    在本例中,我们关注的是LINQ to SQL,这是一种特定的LINQ实现,它用于与关系数据库进行交互,如SQL Server 2005。在VS2008中,LINQ to SQL提供了直观的方式来映射数据库模式到.NET类,从而简化了数据访问。 分页是...

    ASP+SQLserver2000网络书店系统.rar

    在ASP+SQL Server 2000网络书店系统中,SQL Server 2000主要负责存储书籍信息、用户信息、订单等数据,并处理来自ASP页面的数据库操作请求。 **系统功能模块** 1. **用户模块**:包括用户注册、登录、个人信息管理...

    个人博客系统(jsp+sqlserver2000)源代码

    【个人博客系统(jsp+sqlserver2000)源代码】是一个专为初学者设计的项目,旨在帮助他们理解如何构建一个基于Web的博客平台。这个系统利用Java Server Pages (JSP)技术来处理前端展示和后端逻辑,同时借助SQL Server ...

    ASP+SQL Server典型网站建设案例 源代码

    - **数据展示与检索**:如何从SQL Server获取数据并展示在网页上,例如搜索功能、分页显示等。 - **事务处理**:涉及多表操作时,源代码可能会展示如何使用SQL Server的事务管理确保数据一致性。 通过深入研究这...

    精通ASP.NET2.0+SQL Server 2005项目开发 源码.rar

    2. 数据展示与分页:通过GridView、Repeater等控件,演示如何从SQL Server 2005中检索并展示数据,同时实现数据的分页和排序。 3. 多层架构设计:模拟真实项目,展示业务逻辑层(Business Logic Layer, BLL)、数据...

    winform的分页控件,带数据分页

    本文将详细讨论“winform的分页控件,带数据分页”的实现方法、重要性以及相关的技术点。 首先,我们要明白“分页”是什么。在数据管理中,分页是一种将大量数据分割成多个较小部分(页)的策略,每一页可以独立...

    数据分页显示

    建议下载并仔细研究该文件,以便更深入地理解JSP中数据分页的实现过程。 总的来说,数据分页显示是JSP和数据库操作中的一个重要环节,它涉及到数据库查询优化、服务器资源管理以及用户交互设计。通过合理的分页,...

    大工论文 基于Web的分页技术的研究与实现.docx

    在本文中,我们使用了ASP来实现分页技术,因为ASP具有易于编程,无需编译的特点,数据库使用的是Ms SQL server,因为MsSQL数据库和ASP同属MS的产品,开发时更加高效。本文中的ASP页面不仅实现了基本的分页显示技术,...

    SQL Server 2005数据库管理与应用高手修炼指南配套文件

    通过《SQL Server 2005数据库管理与应用高手修炼指南》的配套文件,读者可以找到实战练习和案例研究,加深对上述知识点的理解和应用。这些文件可能包括练习数据库、示例脚本、解决方案模板等,帮助读者在实践中提升...

    ASP.NET 2.0+SQL Server 2005数据库开发与实例 第10章BBS系统录像

    2. **SQL Server 2005**:作为Microsoft的旗舰级关系型数据库管理系统,SQL Server 2005提供了强大的数据存储和处理能力。在本实例中,我们将学习如何设计数据库结构、创建表、设置关系以及执行SQL查询。 3. **...

    SQL Server 2005下T-SQL增强功能的研究和应用.pdf

    文章通过一个教学评价系统的例子展示了如何使用ROW_NUMBER()结合通用表表达式(CTE)来实现高效的数据分页查询,这样只需要返回当前页的数据行,大大提高了查询效率。 文章还回顾了在SQL Server早期版本中获取排名...

    ASP+NET百万级分页控件 强大免费

    通常,我们可以使用`OFFSET-FETCH`(SQL Server 2012及以上版本)或`ROW_NUMBER() OVER (ORDER BY ...)`子句来获取指定范围的数据。对于DBA(数据库管理员)来说,优化这些查询以减少I/O操作和提高查询速度至关重要...

    数据分页查询控件(含源码与Demo).rar

    数据分页查询控件在IT领域中是一种常见且重要的组件,尤其在开发数据库驱动的应用程序时,用于处理大量数据的展示。"数据分页查询控件(含源码与Demo).rar" 提供了实现这一功能的具体代码示例和演示项目,这对于...

    bbs.rar_bbs_bbs sqlserver java_java BBS_simple bbs java_sqlserve

    【标题】"bbs.rar_bbs_bbs_sqlserver_java_java_BBS_simple_bbs_java_sqlserver"揭示了这个压缩包是一个关于论坛(BBS)开发的资源,主要涉及到的技术栈是Java编程语言和SQL Server数据库系统。这个简单的Java BBS...

    jquery ajax asp 分页 翻页 代码示例

    在ASP(Active Server Pages)开发中,结合jQuery的AJAX(Asynchronous JavaScript and XML)功能,可以实现数据的动态加载和分页效果,提供更流畅的用户体验。本示例将详细解析如何使用jQuery AJAX实现ASP分页功能...

    SQL分页控件源码20130206

    这可能涉及到SQL Server的`TOP`子句、`OFFSET/FETCH`或`LIMIT/OFFSET`(取决于数据库系统),以及如何动态调整查询条件来适应分页需求。同时,控件还需要处理页码导航、每页记录数的设置以及总页数的计算等功能。 ...

Global site tag (gtag.js) - Google Analytics