`
cats_tiger
  • 浏览: 276562 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

关于分页查询的疑惑

阅读更多
以前发在CSDN的一篇blog,但是没有人回复。这是我一直疑惑的问题。原文如下:
http://blog.csdn.net/catstiger/archive/2006/08/31/1148015.aspx

分页查询是经常能够遇到的问题,我们首先看看分页查询存在的理由:

    方便用户:用户不可能一次察看所有数据,所以一页一页的翻看比较好。
    提高性能:一次从数据库中提取所有数据会比较慢。
那么现在我来尝试反驳上述理由:

真的方便吗?我们考虑下面的情况
[list=]如果数据只有20条。
如果数据超过1000条。[/list]
第一种显然不必分页查询。奇怪的是第二种也不必,因为没有哪个用户愿意一页一页的翻到最后,如果用户查询到的数据超过了他所关心的数据范围,我认为应该让他重新输入查询条件,就像我们使用google一样。
但是作为一个友好的应用界面,我们总是希望用户可以全面的了解他的查询结果,所以有必要告诉用户:“你查到了多少数据,但是,目前只能显示前1000条,如果您希望察看所有数据,那么应该如何如何... ”
性能会提高吗?
如果数据量很小,显然性能不会有明显的提升,相反,性能会大大下降。因为数据库执行了不必要的查询和查询条件。
如果数据量很大,性能也不见得有明显提升,因为你总是要执行一个额外的count查询。当然,这要看实际情况了。
可以想像,分页查询对于性能的影响和数据量之间的关系应该是一个曲线,数据量小的时候会降低性能,数据量大的时候可能(根据不同的数据库)会提升性能。关键是通过测试,找到曲线的拐点。性能不是根据经验和感觉得到的,而是通过测试得到的
另外,如果一次全部取出数据,的确会造成空间性能的影响,但是,现在内存很便宜...
分页查询的负面影响
对于一个架构良好的web应用,将pageNo和PageSize在各个类之间传递实在是不爽,这两个数据明显属于表现层。
分页查询还会明显提高编程复杂度。
奇怪的现象:为什么没有一个大型数据库直接提供分页查询?Oracle的RowNo不是用于分页的,SQLServer的Top更不是。
结论
ExtremeTable、DisplayTag、JSF DataTable都提供了简单的分页方式,那就是在结果集合中分页。使用非常方便,而且使得逻辑清晰,大大提高了工作效率。绝大多数情况下,可以直接使用这种方式。
如果通过测试,发现上述方式影响了性能,那么考虑使用分页查询。
对于用户量很大的应用,因为内存的原因,也可以考虑分页查询。但是,我个人更推荐缓存方式:同样的查询放在一个缓存中...
采用合理的设计,屏蔽开发人员处理分页逻辑。比如,将分页逻辑和count查询放在父类,开发人员负责组合查询条件。具体看设计模式吧。
欢迎大家讨论!!!

分享到:
评论
38 楼 kimfly 2006-10-27  
对记录缓存存在疑问,这样的策略好像不太适合实际情况。用户数据更改后一直看不到变化。
现在存在的另一个问题是如果用户修改记录后分页的页数变了,如何定位当前页呢。
37 楼 it_weigang 2006-10-27  
     
36 楼 dwangel 2006-10-26  
cats_tiger 写道
引用
除了session里面不放大量东西这个常识以外

从来也不会把数据忘session中缓存的,缓存方案很多,这个最烂。
引用
count的影响确实不大。重建索引就可以。200万的一个表中,没建索引之前,count需要20多秒,建了索引,0.n秒就可以了。

关键问题就在这里,你不能保证每个查询都走索引,尤其是你不能保证每个人都能做到这样。不走索引,任何查询都慢。
还有你说分页没有什么值得讨论的,我也不同意。任何好的思路都有使用范围,我就是希望能够证实我所总结的这个范围是正确的。


正因为不是每个人查询都能够做到充分利用索引,所以分页查询里就涉及到对数据的分析和掌握。
那么,数据库不直接提供分页功能也就比较合理了。
因为,提供了分页,却不能保证性能。
要性能就要用户自行调优,这就是用户应用层面的东西了。
35 楼 smilelee74 2006-10-26  
如果用户输入一个查询条件得到10万条数据,你不分页难道等死啊
我们来看看结果。
分页,只返回10条记录,用户感觉很爽,这么快就得到答案了。
不分页,返回10万条记录,用户可以重启系统了。。。
34 楼 叶子 2006-10-25  
刚特意插了102w记录(mssql)

翻页到1000000记录时候的分页存储过程执行时间 29XX ms

count 102w记录的  是15XX ms

字段就三个
id,name,pass

count和分页条件都是空,排序空.
id主键.name索引.



33 楼 抛出异常的爱 2006-10-25  
人身攻击的不要.....

分页有传统方式
传统方式有以下好处:
1好用
2稳定
3教的快
4对于海量数据(我见过10W数据的程序)可达到目的


新的想法有什么好处还不很清楚
但没人尝试怎么才会进步呢?
32 楼 cats_tiger 2006-10-25  
引用
除了session里面不放大量东西这个常识以外

从来也不会把数据忘session中缓存的,缓存方案很多,这个最烂。
引用
count的影响确实不大。重建索引就可以。200万的一个表中,没建索引之前,count需要20多秒,建了索引,0.n秒就可以了。

关键问题就在这里,你不能保证每个查询都走索引,尤其是你不能保证每个人都能做到这样。不走索引,任何查询都慢。
还有你说分页没有什么值得讨论的,我也不同意。任何好的思路都有使用范围,我就是希望能够证实我所总结的这个范围是正确的。
31 楼 kabbesy 2006-10-25  
Lucas Lee 写道
你的疑问很好。

BTW,我不使用缓存的原因,并不仅是因为性能的考虑,而主要是:
1)你将几万甚至几十万的记录缓存在session里,(应该是放在这里吧?),你不觉得session里放大量东西会严重影响性能么?这个应该算是常识吧。
2),你什么时候更新缓存?用户想看到自己或其他用户添加、更改的内容,你用什么逻辑去更新?是否要考虑线程安全性?深入点,你会发现实际所有使用缓存的方法都会有类似的问题,所以特别是在数据库应用中,我会对数据内容缓存(非配置数据)持非常谨慎的态度。

而对于性能来说,我的一个主要观点是:
(我的假设,对一般情况而言)如果用户发现数据非常大,在一般情况下,不会依次查看每页记录,而会更改查询条件或排序方式,使结果更容易读。如果我的假设成立,那么显然,将所有记录都load到缓存里的方法,将有大部分的内容是不会用到的。所以,以前有些数据库查询的设计是,超过一千条的记录,只显示前一千条,和总记录数,这种设计,不是没有道理的,但显然数据库分页的方式比这种更好些,而且保持了类似的性能。


除了session里面不放大量东西这个常识以外
还应该有一个常识:缓存一切可以缓存的资源。
30 楼 together 2006-10-25  
absolute虽然这个方法每个jdbc驱动都有,但是实现的具体方法和效率是不一样的。
count的影响确实不大。重建索引就可以。200万的一个表中,没建索引之前,count需要20多秒,建了索引,0.n秒就可以了。

不过如果真是百八十万条以上的分页,还是先让用户输入查询条件更为合适。或者默认限定查询条件。
29 楼 叶子 2006-10-25  
together 写道
count查询对性能影响并不大,而且数据库本身可以缓存SQL的。
cats_tiger 写道
PS.很多用户要求根据任意列排序(就像C/S方式),这个需求和分页结合起来也很麻烦。如果直接采用Taglib提供的功能就简单多了。

这个实现起来也很easy,并没有什么难的。传几个参数而已。按任意列排序和模糊查询都非常容易实现的

另:分页,是一个不需要讨论的话题。就像为什么要OO,为什么要有软件工程一样。



count影响不大?

mssql里 无聊把23w ip库的记录insert到100w

count下,时间很恐怖的,比top翻最后一页所花时间都多.
28 楼 LucasLee 2006-10-25  
together 写道
叶子 写道

这个count可以在条件不变情况下缓存,比如bbs就可以把某个板块的帖子数目存板块表里面
sql2005有朋友使用了,不过没听他们说过有分页函数(也有可能他们还没摸那么深).
不过不能不说,mssql在分页上确实有点混蛋:(

count缓存也是不太保险的,实现起来容易,但要保证数据的完全一致,有点困难。
这个倒是冤枉了mssql。虽然它没有像oracle/mysql提供内置的分页方法,但是用游标定位的方式,还是可以快速的实现分页的。在asp中,ADO提供了resultset的PageSize和AbsolutePage函数,也是采用游标定位。假如你要每页显示30条,定位到第2页,这样写就可以实现:rs.PageSize=30  rs.AbsolutePage=2

传说sqlserver2005提供了内置分页功能,这是真的。2005中也像oracle一样有rownum,它的分页方式和oracle采用rownum分页语句很相似。


你说的这个游标方式是数据库通用的,等同于JDBC里的Result.absolute()方法,一样,也是通用的。
但这个性能比数据库专有的方法要慢。
有的时候可以结合两种方法来实现,比如对于SQLSERVER2000,
在SQL中使用top来限制一部分记录,比如你要显示100--120记录,则select top 120,然后再使用Result.absolute()。
27 楼 together 2006-10-25  
count查询对性能影响并不大,而且数据库本身可以缓存SQL的。
cats_tiger 写道
PS.很多用户要求根据任意列排序(就像C/S方式),这个需求和分页结合起来也很麻烦。如果直接采用Taglib提供的功能就简单多了。

这个实现起来也很easy,并没有什么难的。传几个参数而已。按任意列排序和模糊查询都非常容易实现的

另:分页,是一个不需要讨论的话题。就像为什么要OO,为什么要有软件工程一样。

26 楼 robbin 2006-10-25  
cats_tiger 写道
正是因为一个多余的count查询,所以才感觉分页查询不见得能够提高性能。当然,性能必须通过测试获得,凭感觉和经验是不行滴。我所接触的项目中,多数表可以预测一个大概的记录总数。如果记录总数<10k,我们就不采用分页查询了,而是利用extremeTable、DisplayTag或Tomahawk DataTable之类的taglib来分页。
PS.很多用户要求根据任意列排序(就像C/S方式),这个需求和分页结合起来也很麻烦。如果直接采用Taglib提供的功能就简单多了。
另外,用absolut定位光标的方式和用List.subList的方式不知道哪个更快。
引用
BTW:Microsoft从来都是针对最终消费者的体验好,针对程序员,就难说了。

MS还是很能体会程序员的辛苦的,看看.Net IDE,Java这么多IDE没有一个比得上。


Visual Studio在代码功能上和Eclipse相比,差的太遥远了。

http://www.cnblogs.com/dflying/archive/2006/10/20/535210.html

25 楼 cats_tiger 2006-10-25  
正是因为一个多余的count查询,所以才感觉分页查询不见得能够提高性能。当然,性能必须通过测试获得,凭感觉和经验是不行滴。我所接触的项目中,多数表可以预测一个大概的记录总数。如果记录总数<10k,我们就不采用分页查询了,而是利用extremeTable、DisplayTag或Tomahawk DataTable之类的taglib来分页。
PS.很多用户要求根据任意列排序(就像C/S方式),这个需求和分页结合起来也很麻烦。如果直接采用Taglib提供的功能就简单多了。
另外,用absolut定位光标的方式和用List.subList的方式不知道哪个更快。
引用
BTW:Microsoft从来都是针对最终消费者的体验好,针对程序员,就难说了。

MS还是很能体会程序员的辛苦的,看看.Net IDE,Java这么多IDE没有一个比得上。
24 楼 叶子 2006-10-25  
together 写道
叶子 写道

这个count可以在条件不变情况下缓存,比如bbs就可以把某个板块的帖子数目存板块表里面
sql2005有朋友使用了,不过没听他们说过有分页函数(也有可能他们还没摸那么深).
不过不能不说,mssql在分页上确实有点混蛋:(

count缓存也是不太保险的,实现起来容易,但要保证数据的完全一致,有点困难。
这个倒是冤枉了mssql。虽然它没有像oracle/mysql提供内置的分页方法,但是用游标定位的方式,还是可以快速的实现分页的。在asp中,ADO提供了resultset的PageSize和AbsolutePage函数,也是采用游标定位。假如你要每页显示30条,定位到第2页,这样写就可以实现:rs.PageSize=30  rs.AbsolutePage=2

传说sqlserver2005提供了内置分页功能,这是真的。2005中也像oracle一样有rownum,它的分页方式和oracle采用rownum分页语句很相似。


是不太保险,需要自己考虑有数据更改情况下更新.

^_^,偶就是写asp出家的,对这个很熟悉.游标的性能,也就那么回事吧.

AbsolutePosition,AbsolutePage对ac是速度最快的,不过对mssql是噩梦.

另扯一句,asp里缓存count,对ac AbsolutePosition,对mssql用top ,之后再getrows,速度是最快滴.
23 楼 together 2006-10-25  
叶子 写道

这个count可以在条件不变情况下缓存,比如bbs就可以把某个板块的帖子数目存板块表里面
sql2005有朋友使用了,不过没听他们说过有分页函数(也有可能他们还没摸那么深).
不过不能不说,mssql在分页上确实有点混蛋:(

count缓存也是不太保险的,实现起来容易,但要保证数据的完全一致,有点困难。
这个倒是冤枉了mssql。虽然它没有像oracle/mysql提供内置的分页方法,但是用游标定位的方式,还是可以快速的实现分页的。在asp中,ADO提供了resultset的PageSize和AbsolutePage函数,也是采用游标定位。假如你要每页显示30条,定位到第2页,这样写就可以实现:rs.PageSize=30  rs.AbsolutePage=2

传说sqlserver2005提供了内置分页功能,这是真的。2005中也像oracle一样有rownum,它的分页方式和oracle采用rownum分页语句很相似。
22 楼 叶子 2006-10-25  
更正:

刚google了下,mssql2005确实有ROW_NUMBER来解决分页问题的.

demo语句:

select threadid from (select threadid, ROW_NUMBER() OVER (order by stickydate) as Pos from cs_threads) as T where T.Pos > 100000 and T.Pos < 100030
21 楼 叶子 2006-10-25  
cats_tiger 写道
引用 写道

分页很简单啊,没有多运行什么所谓的查询条件,只是当查询出等于pageSize的数量时暂停查询而已啊,已经查出来的数据会放在数据库缓存中,等再次查询时,也可以提高数据库缓存命中率。不能理解性能如何大大下降啊。

我所说的“额外的查询”是指那个count查询,如果不加查询条件,count是很快的,如果加查询条件并且不走索引,count查询就很慢了。多数分页查询,都要执行一个count查询吧,它不会影响性能吗?


这个count可以在条件不变情况下缓存,比如bbs就可以把某个板块的帖子数目存板块表里面

sql2005有朋友使用了,不过没听他们说过有分页函数(也有可能他们还没摸那么深).

不过不能不说,mssql在分页上确实有点混蛋:(
20 楼 robbin 2006-10-25  
cats_tiger 写道
引用
这并不奇怪。
只能说楼主没有仔细想过数据库查询的基本方法。
一个简单的两个表的inner join,如果要分页,就需要首先得到整个结果集的数量。而仅仅通过top, limit限定范围,则只需要达到限制的数量就可以了。 top 和 limit实现,要比分页简单多了。
所以数据库设计者,是将分页交给用户来作处理而已。
不实现分页不是说分页没有用。

还是很奇怪呀,分页的确比limit复杂,正因为如此,数据库设计者才不应该把这个工作交给用户。SQLServer压根就没有为分页查询提供可能的技术,Oracle好歹还有一个ROW_NUM,SQLServer的top...唉!这种情况显然与MS的一贯做法不同,MS向来重视客户体验。
实际上,对于数据库设计者来说,提供一个分页功能实在是太简单了。


传言SQL Server 2005提供了分页SQL,不知道是不是真的。

SQL Server可以使用sp_系统存储过程来移动游标实现数据库端分页。

BTW:Microsoft从来都是针对最终消费者的体验好,针对程序员,就难说了。

19 楼 cats_tiger 2006-10-25  
引用
这并不奇怪。
只能说楼主没有仔细想过数据库查询的基本方法。
一个简单的两个表的inner join,如果要分页,就需要首先得到整个结果集的数量。而仅仅通过top, limit限定范围,则只需要达到限制的数量就可以了。 top 和 limit实现,要比分页简单多了。
所以数据库设计者,是将分页交给用户来作处理而已。
不实现分页不是说分页没有用。

还是很奇怪呀,分页的确比limit复杂,正因为如此,数据库设计者才不应该把这个工作交给用户。SQLServer压根就没有为分页查询提供可能的技术,Oracle好歹还有一个ROW_NUM,SQLServer的top...唉!这种情况显然与MS的一贯做法不同,MS向来重视客户体验。
实际上,对于数据库设计者来说,提供一个分页功能实在是太简单了。

相关推荐

    页面列表实现假分页

    4. **Hibernate查询**:利用Hibernate的Criteria API或者HQL(Hibernate Query Language)来执行分页查询。这里不是传统的`setFirstResult()`和`setMaxResults()`方法,而是根据前端传递的参数,如当前加载的条目...

    非常好用的jsp分页标签

    这意味着可能有社区或作者提供技术支持,帮助解决使用过程中的疑惑。 总的来说,这个"非常好用的jsp分页标签"简化了Web开发中的分页工作,使开发者可以更专注于业务逻辑,而非重复的页面布局代码。通过合理利用,...

    AspNetPager免费分页控件7.02chm帮助文档。

    5. **动态参数传递**:可以在分页过程中传递额外的查询参数,实现更复杂的数据过滤。 6. **多语言支持**:控件内置多国语言支持,方便国际化应用的开发。 7. **兼容性**:AspNetPager兼容各种版本的ASP.NET,包括...

    操作系统学习常见疑惑问与答

    - **内存管理**:包括虚拟内存、分页、分段、内存分配与回收等机制。 - **文件系统**:设计用于组织、存储和检索文件的结构,如FAT、NTFS、EXT等。 - **设备驱动**:是操作系统与硬件设备之间的桥梁,负责设备的初始...

    ASP技术常遇问题解答-如何编写翻页函数?.zip

    本资料将聚焦于如何在ASP中编写翻页函数,以帮助开发者解决这方面的疑惑。 在ASP中实现翻页功能,主要涉及以下几个核心知识点: 1. 数据库连接:首先,我们需要与数据库建立连接,通常使用ADO(ActiveX Data ...

    下拉加载数据

    后端应优化查询逻辑,确保根据前端的需求进行分页查询,避免一次性返回过多数据导致性能问题。 在实际应用中,下拉加载数据还有以下几个关键点: - **延迟加载(Lazy Loading)**:为了进一步优化性能,可以采用...

    网页底部加载更多内容的控件

    2. 用户反馈:加载过程中应有明显的加载状态提示,避免用户疑惑是否在加载。 3. 性能优化:为了防止过多的请求和数据加载,可以设置加载阈值,如用户停止滚动一段时间后再进行加载。 4. 可访问性:考虑到不同用户的...

    瀑布流 无限加载图片

    利用媒体查询(Media Queries)可以实现响应式布局,根据设备的视口宽度调整元素大小和布局。 5. **性能优化**:无限加载可能导致大量图片一次性加载,影响页面性能。为了优化,可以使用懒加载(Lazy Loading)技术...

    #pragma用法_汇总.doc

    `#pragma`是C语言中的一种预处理器指令,用于向编译器提供特定的命令或信息,以控制编译过程。在嵌入式系统开发,尤其是针对...希望这些信息能解答大家关于`#pragma`用法的疑惑,并帮助你更好地理解和使用这些功能。

    基于ssm+mysql的花卉养殖知识平台源码数据库.docx

    - **分页查询**:为了提高用户体验,避免一次性加载过多数据,采用分页技术进行数据展示。 - **搜索功能**:实现模糊查询功能,让用户能够更方便地找到所需信息。 - **安全机制**:加强用户密码加密、防止SQL注入等...

    Infinite-Scroll无限滚动加载数据

    当数据正在加载时,可以显示一个加载指示器,防止用户疑惑为何没有新内容出现。加载完成后,可以清除指示器并展示新内容。 8. **错误处理**:考虑网络错误或服务器故障的情况,应提供适当的错误提示,并且允许用户...

    UI(用户界面)设计规则和规范[定义].pdf

    以下是关于UI设计的一些核心规则和规范: 1. **易用性**: - 按钮命名应清晰,避免模糊不清的词汇,易于与其他按钮区分,并能直观反映其功能。 - 功能相似的按钮可以用框架框起,支持快捷键操作,方便用户快速...

    Jsoup爬笔趣阁小说

    在**爬虫**过程中,为了下载笔趣阁所有的小说,我们需要遍历网站的目录结构,通常这涉及到对分页和链接的处理。可以使用Jsoup获取每一页的链接,然后递归地处理每个页面,直到遍历完所有小说列表。同时,为了避免...

    Axure夜话之程序员眼中的原型设计视频教程之循环操作之固定次数循环

    "Axure夜话学习交流群.txt"可能提供了一个社区平台,让你与其他学习者交流经验,解答疑惑。而"爱上原型Axure.url"和"老二牛车教育.url"可能是相关的网站链接,你可以访问这些网站获取更多的学习资源和教程。 总的来...

    软件工程-课程设计(在线答疑系统).pdf

    该系统旨在为学生、教师和管理员提供一个互动平台,解决学习中的疑惑。 1. 需求分析: - 功能性需求分析:系统针对学生、教师和管理员设置了不同的功能。学生可以注册、登录、修改个人信息,并提问或回答问题;...

    java实训报告(简单人事管理系统的设计与实现).doc

    提供一个列表视图展示所有员工和部门,支持分页和排序功能。 #### 3.5 数据信息查询模块 通过输入关键字,系统在员工和部门表中进行匹配,返回匹配结果。 #### 3.6 帮助模块 提供系统使用说明和常见问题解答,...

    仿淘宝继续拖动显示详情页

    5. **数据分页**:为了优化性能,服务器不会一次性返回所有数据,而是采用分页策略,每次只返回一部分。前端根据需要请求不同页码的数据。 6. **滚动触发距离**:设置合适的滚动触发距离是优化用户体验的关键。太早...

    layui中文离线文档.rar

    layui的核心特点是模块化,它的组件包括布局、表格、表单、按钮、图标、弹层、加载、工具提示、滚动条、切换、时间轴、进度条、树形结构、分页、图表等。这些组件设计简洁,易于理解和使用,使得代码组织更加规范,...

    基于用户体验的链接策略.docx

    合理的做法是将内容分页或进行有效的分类,以便用户更容易导航。 总之,基于用户体验的链接策略是一个综合性的设计过程,涉及到信息架构、可用性、视觉设计和交互设计等多个方面。通过精心策划和实施这些策略,可以...

    ajax从入门到精通

    - **用户体验**:Ajax请求可能会导致页面状态混乱,因此在请求期间应显示加载指示器,避免用户疑惑。 通过学习和实践这些Ajax开发实例,你将能深入理解Ajax的工作机制,并熟练地在项目中应用Ajax技术,提升网页的...

Global site tag (gtag.js) - Google Analytics