朱燚

--书到读透处,酒于微醺时

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  61 随笔 :: 21 文章 :: 445 评论 :: 37 引用

我们先给出几种主要的分页方法和核心语句,然后直接给出结论,有兴趣的读者可以看看后面的数据

几种常用存储过程分页方法

TopN方法

select Top(@PageSize) from TableName where ID Not IN  

(Select Top ((@PageIndex-1)*@PageSize)  ID from Table Name where .... order by ... )

where .... order by ...

临时表

declare @indextable table(id int identity(1,1),nid int,PostUserName nvarchar(50))

declare @PageLowerBound int

declare @PageUpperBound int

set @PageLowerBound=(@pageindex-1)*@pagesize--下限

set @PageUpperBound=@PageLowerBound+@pagesize--上限

set rowcount @PageUpperBound

insert into @indextable(nid,PostUserName) select ReplyID,PostUserName from  TableName order by ......

select *  from  TableName p,@indextable t where p.ID=t.nid

and t.id>@PageLowerBound and t.id<=@PageUpperBound order by t.id

CTE--2005新语法,类似临时表,但是生命周期稍微不同,这里只是他的一个运用

with cte_temp--定义零时表,PageIndex是一个计算字段,储存了搜索结果的页号

 As (ceiling((Row_Number() over(order by .... )-1)/@pagesize as int) as PageIndex,* from TableName where.....)
select *  from cte_temp where pageindex=@pageindex-1;

结论:

TopN在小页数下最快,如果在10页以下,可以考虑用它,CTE和临时表时间很稳定,CTE消耗的时间比临时表多,但是不会引起tempdb的暴涨和IO增加

性能比较

试验环境:win2003server,Sqlserver2005,库大小2,567,245行,没有where子句,试验时每页大小50,页码作为变量

取0,3,10,31,100,316,1000,3162...页,也就是10的指数,试验结果如下

页数 TopN CTE 临时表 临时表 老论坛存储过程 CTE改进
1 3 12 10 101 457 7302
3 15 7 79 5524 464 7191
10 127 5504 88 3801 464 6116
32 588 9672 122 3601 976 7602
100 4680 9738 166 4235 486 7151
316 45271 9764 323 3867 522 7255
1000 无法计算 9806 869 2578 635 8948
3162 无法计算 9822 2485 4110 12460 8210
10000 无法计算 9754 7812 11926 14250 7359
31623 无法计算 9775 18729 33218 15249 7511
100000 无法计算 无法计算 31538 55569 17139 6124

数据解释和分析

临时表分为有没有缓存两种时间,CTE就是上面的方法,CTE改进只是把选入CTE临时表的列数减少了,只选取了页号和主键,Null表示时间无法计算(时间太长),数据单位是毫秒.

从上面的数据可以看到,TopN在前32页都是有优势的,但是页数增大后,性能降低很快,CTE改进比CTE有所进步,平均进步两秒左右,但是还是比临时表慢,但是考虑临时表会增大日志文件的大小,引起大量IO,CTE也就有他自己的优势,公司现在正在使用的存储过程效率不错,但是在页码靠后的情况下性能会降低

posted on 2007-07-01 20:53 朱燚:-) 阅读(5019) 评论(28)  编辑 收藏 所属分类: 数据库性能

评论

#1楼  2007-07-01 21:13 zoti [未注册用户]
好东西,沙发
  回复  引用    

#2楼  2007-07-01 21:15 GOFI XIAO      
不错。
  回复  引用  查看    

#3楼  2007-07-01 21:47 YAO.NET(三千)℡      
"TopN在小页数下最快",其实页数少时,记录也一般都不多,这时候我觉着随便一种分页都不会有大问题.


  回复  引用  查看    

#4楼  2007-07-01 22:13 sf [未注册用户]
╔─────────────----╗
│ *^_^* │
│ 博友乐园  │ 
│ 欢迎来到ghb的博客│
│ 希望博友们喜欢给予支持 |
│ ghb.blogbus.com
╚──────────────--╝
  回复  引用    

#5楼  2007-07-01 23:49 nzperfect [未注册用户]
不如去看看我的分页,肯定快
  回复  引用    

#6楼  2007-07-02 00:49 曲滨*銘龘鶽      
分页类的东西,如果不是数据库有针对性优化
怎么都不可能太快,尤其是那种没唯一数字字段的表

Oracle 还可以,SQL Service 即使是2005也很郁闷 Row_Number() 也不是很好用
  回复  引用  查看    

#7楼  2007-07-02 01:22 pwqzc [未注册用户]
在firefox浏览器里面用这个编辑框回复
按下回车键会生成什么呢?\n还是?
郁闷
  回复  引用    

#8楼  2007-07-02 01:42 维生素C.NET      
hoho,你终于搬到博客园了,期待你更多的好文章:)
  回复  引用  查看    

#9楼  2007-07-02 06:16 xmlcss [未注册用户]
使用Read 分页 比上面两种方法都要快
  回复  引用    

好像没有利用索引。
  回复  引用  查看    

#11楼  2007-07-02 08:30 ddr888      
总结的时候应该弄个楼主推荐奖,
分析的用的什么工具?
  回复  引用  查看    

#12楼  2007-07-02 09:59 冬冬      
一直在用TopN,每涉及到大数据量,性能比较满意,觉得数据量上出去了,分页的出发点也就要变了。
  回复  引用  查看    

#13楼  2007-07-02 10:06 pgmfan [未注册用户]
高手,你这图是怎么画的
  回复  引用    

#14楼  2007-07-02 11:05 没剑      
分页类的东西,如果不是数据库有针对性优化
怎么都不可能太快,尤其是那种没唯一数字字段的表

Oracle 还可以,SQL Service 即使是2005也很郁闷 Row_Number() 也不是很好用
---
同意楼上的说法。要有针对性的对where作一些索引的优化
  回复  引用  查看    

#15楼  2007-07-02 11:46 万宇华 [未注册用户]
用TopN分页,数据量大的时候加上max或min,根据排序的方式进行选择.
但有主键ID无序的时候分不了页!
  回复  引用    

有空我写一个全一点的分页算法和测试吧。感觉这个不是太全,考虑的因素也不是太多。原以为在博克园里分页应该是不成问题的呢,不知道是不是高手都还没有发表意见呢。
  回复  引用  查看    

#17楼  2007-07-02 14:12 Randy [未注册用户]
LZ的性能分析很有用,下面这篇文章也不妨看一下,对方法总结的蛮全

Custom Paging in ASP.NET 2.0 with SQL Server 2005
http://aspnet.4guysfromrolla.com/demos/printPage.aspx?path=/articles/031506-1.aspx
  回复  引用    

#18楼  2007-07-02 14:55 yi      
如果数据量不是非常大直接使用CTE就能满足需求
  回复  引用  查看    

#19楼  2007-07-02 16:12 microant      
好东西,学习
  回复  引用  查看    

#20楼  2007-07-02 23:20 mwtcz [未注册用户]
你的测试数据我怎么看不明白, 我想top n的方式应该算是比较常用的方式,我的程序一直都是使用,数据量也有那么几百万条,也没出现几百页后不能计算的情况。分页,对于不同的表,不同的索引,效率是不同的,你应该把你的表结构,索引结构全都写出来,这样的测试才比较全面。

用索引表的方式看不太懂,是不是把表的内容全导进一个表变量里再进行分页处理?如果是这样我想可能会很耗内存,测试数据不能只想只有一个客户端,在生产环境里,大家频繁使用这个存储过程,不停的把几百万条数据装进一个表变量里然后再读,感觉不是很妥当。

CTE的方式没用过,不做评论。

还是希望楼主把测试的全过程写清楚,这样也便于大家分析。
  回复  引用    

#21楼  2007-07-03 17:22 JoeLee [未注册用户]
真不知道这么多人研究分页做什么。你没看我们的SQL语句后便WHERE部分的长度。你这个数据太简单了。做了分区及索引后,自然会优化。你这都研究到临时表里边去了。服了。

这种东西交给硬件或设计去解决好了。难道你是做科研的?研究细小效率。反正作为我们做应用的来讲,如何完成复杂的逻辑功能才是最重要的。
  回复  引用    

#22楼  2007-07-03 17:24 JoeLee [未注册用户]
再说你这只是小技巧而已。又不是什么改进B树查找速度的算法。每个人编写不同的部分有不同的技巧。不见得你这个东西能快到那里。
  回复  引用    

#23楼  2007-12-04 13:08 fjyou [未注册用户]
@nzperfect
你哪有分页代码呀
  回复  引用    

#24楼  2007-12-05 11:09 boy5d [未注册用户]
收藏
  回复  引用    

#25楼  2008-04-09 21:26 可耕地 [未注册用户]
i qja go g wh !~
  回复  引用    

#26楼  2008-05-23 15:31 CsharpFish      
很精彩,谢了,引用
  回复  引用  查看    


标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2007-12-04 22:20 编辑过


相关链接: