数据分页获取(一)
今天的应用程序所承载的数据量都是非常大的,千万条记录的比比皆是(俺上家就是)。如何高效而准确地将所需的数据从数据库中获取到应用程序里,就变得非常的重要了。
本文要讲的是数据分页获取(也叫数据分页查询,但我更喜欢叫成数据分页获取),就是针对大数据量的情况下,利用分页技术,一次性只从数据库获取所需的小部份数据返回给应用程序。此技术能够减少在应用程序服务器和数据库服务器之间传输的数据量、减少一次性加载到内存的数据量,提高应用程序的整体性能 !有这么多好处,在实际开发中肯定会应用到的(事实也是这样),所以也就是必须掌握的技术了。
网络上流传有很多种数据分页技术。有应用程序级的分页技术,有数据库级的分页技术,而数据库级的分页技术在不同的数据库平台又有不一样的实现技巧(当然,应用程序级的分页技术也一样!)。本文要讲的就是数据库级的分页技术,因为个人觉得数据库级的分面技术才是真正高效、准确而且稳定的。主要讲下两种数据库平台下的分页技巧——SQL Srver和Oracle。先来讲解SQL Server平台下的(适用于SQL Server 2005及更高版本的SQL Server),Oracle平台的后面补上(现在很晚了)!
SQL Server平台下的数据库级数据分页获取技术有很多种实现方法,这里我只讲解其中一种最高效的方法:使用SQL Server提供的Top子句,并结合内置函数ROW_NUMBER()来进行分页获取数据。举例如下图所示:
第二:内置函数ROW_NUMBER() 需要over 子句的配合才能给出行号(其实ROW_NUMBER()是排名编号函数中的一种!),因为ROW_NUMBER() 是基于特定的序列给出行号的。所以,如果ROW_NUMBER() 所基于的序列不同,那么相同的行号对应的记录也可能会不同!这个时候就需要注意了,原本放在后面的用于排序结果集的order by子句,现在就直接移至over 子句里就行了,这样即可以对结果集起到排序的作用,又可以使ROW_NUMBER() 在给出行号时有一个可以基于的特定序列!(over 子句还有其他的用法,不要误以为over 子句就只有这种作用)
第三:要为行号那一列取一个别名,方便外层查询利用行号来分页。
第四:用户所给出的查询条件应放在最里层的查询里,并基于此在最里层的查询上使用top子句选出能够满足分页的最小数据量,供外层查询进行最后更精确的分页界定。这样,相比于下图所示的存储过程,在大数据量时效率应该会更高一些(这个我没进行测试,所以只能说应该!)
![](http://images0.cnblogs.com/blog/328015/201301/13184358-8f099991a56d48d3aedf06c6c2c2e0f3.png)
这里需要注意四点:
第一 ,如果查询是不固定的(比如查询条件并不固定),那么存储过程可能就不适用了,此时就需要在应用程序里手动构造查询语句了,但构造出来的查询语句应该是跟上述data_paging存储过程的主体相差无几的!
第二:内置函数ROW_NUMBER() 需要over 子句的配合才能给出行号(其实ROW_NUMBER()是排名编号函数中的一种!),因为ROW_NUMBER() 是基于特定的序列给出行号的。所以,如果ROW_NUMBER() 所基于的序列不同,那么相同的行号对应的记录也可能会不同!这个时候就需要注意了,原本放在后面的用于排序结果集的order by子句,现在就直接移至over 子句里就行了,这样即可以对结果集起到排序的作用,又可以使ROW_NUMBER() 在给出行号时有一个可以基于的特定序列!(over 子句还有其他的用法,不要误以为over 子句就只有这种作用)
第三:要为行号那一列取一个别名,方便外层查询利用行号来分页。
第四:用户所给出的查询条件应放在最里层的查询里,并基于此在最里层的查询上使用top子句选出能够满足分页的最小数据量,供外层查询进行最后更精确的分页界定。这样,相比于下图所示的存储过程,在大数据量时效率应该会更高一些(这个我没进行测试,所以只能说应该!)
![](http://images0.cnblogs.com/blog/328015/201301/12115734-72156043d0064bbcb1ac2fb58c3ddc76.png)
这应该是在SQL Server平台(注意是SQL Server 2005及以上版本中) 最实用和高效的数据库级分页技巧了(我还研究了下其它几种分页技巧,最后觉得都不是最好的,比如利用top N结合order by和not in子句通过差集来分页)。
而对于Oracle平台,因为Oracle提供了rownum关键字,利用此关键字,可以为一个查询返回的结果集附加一个rownum列,Oracle平台的这个rownum关键字集SQL Server中的ROW_NUMBER()函数、Top子句的功能于一身,因此Oracle不提供SQL Server平台里的ROW_NUMBER()函数和Top子句,因为rownum关键字已经可以很好实现相同的功能了。这在分页上,比起SQL Server平台就好用多了!对于Oralce平台下的数据分页,思路跟SQL Server平台差不多,以后有时间再补上了(其实,我之前的工作都是用Oracle的!)。