[百万级]通用分页存储过程.[千万级]实现千万级数据的分页显示!(转)

有关分页 SQL 的资料很多,有的使用存储过程,有的使用游标。本人不喜欢使用游标,我觉得它耗资、效率低;使用存储过程是个不错的选择,因为存储过程是经过预编译的,执行效率高,也更灵活。先看看单条 SQL 语句的分页 SQL 吧。

方法1:
适用于 SQL Server 2000/2005
SELECT   TOP  页大小  *
FROM  table1
WHERE  id  NOT   IN
          (
          
SELECT   TOP  页大小 * ( - 1 ) id  FROM  table1  ORDER   BY  id
          )
ORDER   BY  id

方法2:
适用于 SQL Server 2000/2005
SELECT   TOP  页大小  *
FROM  table1
WHERE  id  >
          (
          
SELECT   ISNULL ( MAX (id), 0
          FROM  
                (
               
SELECT   TOP  页大小 * ( - 1 ) id  FROM  table1  ORDER   BY  id
                ) 
A
          )
ORDER   BY  id

方法3:
适用于 SQL Server 2005

SELECT   TOP  页大小  *  
FROM  
        (
        
SELECT  ROW_NUMBER()  OVER  ( ORDER   BY  id)  AS  RowNumber, *   FROM  table1
        ) A
WHERE  RowNumber  >  页大小 * (页数 - 1 )


说明,页大小:每页的行数;页数:第几页。使用时,请把“页大小”和“页大小*(页数-1)”替换成数字。

 

 

 

其它的方案:如果没有主键,可以用临时表,也可以用方案三做,但是效率会低。
建议优化的时候,加上主键和索引,查询效率会提高。

通过SQL 查询分析器,显示比较:我的结论是:
分页方案二:(利用ID大于多少和SELECT TOP分页)效率最高,需要拼接SQL语句
分页方案一:(利用Not In和SELECT TOP分页)   效率次之,需要拼接SQL语句
分页方案三:(利用SQL的游标存储过程分页)    效率最差,但是最为通用





/*
名称:spAll_ReturnRows
输入:
输出:
调用:
EXEC spAll_ReturnRows 'select * FROM 表名', 页号, 返回记录数, '主键', '排序字段'
spAll_ReturnRows 'select * FROM all_Categories',2,10,'[ID]','[ID]'
说明:[百万级]通用存储过程.分页存储过程..返回指定返回条数、指定页数的记录
作者:Dili J.F. Senders
邮件:diliatwellknow.net
更新:20040610
版权:转述时请注明来源:用思维创造未来的Wellknow.net
*/


create   PROCEDURE  dbo.spAll_ReturnRows
(
@SQL   nVARCHAR ( 4000 ),
@Page   int ,
@RecsPerPage   int ,
@ID   VARCHAR ( 255 ),
@Sort   VARCHAR ( 255 )
)
AS

DECLARE   @Str   nVARCHAR ( 4000 )

SET   @Str = ' select TOP  ' + cast ( @RecsPerPage   AS   VARCHAR ( 20 )) + '  * FROM ( ' + @SQL + ' ) T where T. ' + @ID + '  NOT IN 
(select TOP 
' + cast (( @RecsPerPage * ( @Page - 1 ))  AS   VARCHAR ( 20 )) + '   ' + @ID + '  FROM ( ' + @SQL + ' ) T9 ORDER BY  ' + @Sort + ' ) ORDER BY  ' + @Sort

PRINT   @Str

EXEC  sp_ExecuteSql  @Str
GO




/*
名称:spAll_deleteNoneUnique
输入:要查询的表名和字段列表
输出:
调用:
说明:实现千万级数据的分页显示!--可以在5秒内获取1448万条记录里的第1200页的100条记录,雄不?
作者:铁拳版权:转述时请注明来源:用思维创造未来的Wellknow.net
*/

create   PROCEDURE  GetRecordFromPage
@tblName   varchar ( 255 ),  --  表名
@fldName   varchar ( 255 ),  --  字段名
@PageSize   int   =   10 --  页尺寸
@PageIndex   int   =   1 --  页码
@IsCount   bit   =   0 --  返回记录总数, 非 0 值则返回
@OrderType   bit   =   0 --  设置排序类型, 非 0 值则降序
@strwhere   varchar ( 1000 =   ''   --  查询条件 (注意: 不要加 where)
AS

declare   @strSQL   varchar ( 6000 --  主语句
declare   @strTmp   varchar ( 100 --  临时变量
declare   @strOrder   varchar ( 400 --  排序类型

if   @OrderType   !=   0
begin
set   @strTmp   =  " < ( select   min "
set   @strOrder   =  "  order   by   [ " + @fldName +" ]   desc "
end
else
begin
set   @strTmp   =  " > ( select   max "
set   @strOrder   =  "  order   by   [ " + @fldName +" ]   asc "
end

set   @strSQL   =  " select   top  "  +   str ( @PageSize +  "  *   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 +  "  *   from   [ "
+ @tblName + "
]   where   [ " + @fldName + " ] +   @strTmp   +  "( [ "
+ @fldName + "
] from  ( select   top  "  +   str (( @PageIndex - 1 ) * @PageSize +  "  [ "
+ @fldName + "
]   from   [ " + @tblName + " ]   where  "  +   @strwhere   +  " "
+   @strOrder   +  ")  as  tblTmp)  and  "  +   @strwhere   +  " "  +   @strOrder

if   @PageIndex   =   1
begin
set   @strTmp   =  ""
if   @strwhere   !=   ''
set   @strTmp   =  "  where  "  +   @strwhere

set   @strSQL   =  " select   top  "  +   str ( @PageSize +  "  *   from   [ "
+ @tblName + "
] +   @strTmp   +  " "  +   @strOrder
end

if   @IsCount   !=   0
set   @strSQL   =  " select   count ( * as  Total  from   [ " + @tblName + " ] "

exec  ( @strSQL )

GO

个人研究百万级数据提出问题总结如下: 
1 .除了提高硬件方面 
2 .采取折中方法,一次提出几百万数据也没有什么实在意义 

不过存储过程写的还是很精妙。 

p
= pagesize,n为返回页数,SQL = " select   *   from  product  where  id < 200000

1 .( select   *   from  product  where  id < 200000 as  t 
2 .( select   top  p * (n - 1 ) t.id  from  t  order   by  id  asc as  t1 
3 . select   top  p  *   from  t  where  id  not   in  t1  order   by  id  asc  

SQL: 
select   top  p  *   from  ( select   *   from  product  where  id < 200000 ) t  where  t.id  not   in  ( select   top  p * (n - 1 ) id  from  t  order   by  id  asc order   by  id  asc  
[ 注:子查询里面别名t 其实并不存在,应该用1.重新代替 ]  

SQL存储过程: 
SET   @str = ' select top ' + cast ( @p   as   varchar ( 20 )) + '  * from ( ' + @SQL + ' ) t where t. ' + @ID + '  not in (select top  ' + cast (( @p * ( @n - 1 ))  as   varchar ( 20 )) + '   ' + @ID + '  from ( ' + SQL + ' ) order by  ' + @Sort + ' ) order by  ' + @Sort  

PRINT   @str  

/*
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/wind8303/archive/2009/02/21/3917862.aspx
*/

百万级数据测试结果如下:
//
///result:100W数据
///
///条件:VirtualItemCount=200000
///->转1页 33.924982085712 milliseconds,33.3696042374101 milliseconds,31.1483722093171 milliseconds
///->转1000页 247.380882207096 milliseconds,190.643224208663 milliseconds,240.085262233049 milliseconds
///->转10000页 2393.90201827327 milliseconds,1903.65535284512 milliseconds,1839.06278591273 milliseconds
///
///条件:VirtualItemCount=all
///->1 10.2540965402027 milliseconds,7.47608983823363 milliseconds,15.5991892824367 milliseconds
///->1000 273.380555349912 milliseconds,190.414982909839 milliseconds,217.308345055028 milliseconds
///->10000 1845.92064075183 milliseconds,1951.84974626663 milliseconds,1904.51831168487 milliseconds
///
///2s处理百万数据
//

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/wind8303/archive/2009/02/21/3917862.aspx

转载于:https://www.cnblogs.com/ForFreeDom/archive/2009/09/19/1569855.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值