分页,是web应用程序非常重要的一个课题。数据库的数据可能是几千,几万,几百万行,但我们不可能把几万行数据一次显示在浏览器上面,这样浏览器受不了,用户也受不了。一般的每页显示20行,是一个比较理想的显示状态。
分页主要有两种思路:
1、取出所有符合条件的数据,放到数据集或者内存当中,然后逐页浏览。那么,有可能你每页只需浏览20条记录,但要把几百万行记录取出来。我把这种分页叫做“指针分页”。指针分页法主要是利用数据集的指针(或者集合的下标)来标识。比如,分页要显示20条数据,那么第一页的指针从1开始,第二页的指针从(2-1)*20+1开始,依次类推。“指针分页”适合数据量和并发量不是很高的应用系统,不适合海量的数据查询。
2、对于海量的数据查询,看多少取多少,显然是最佳的解决办法。假如某个表中有200万条记录,第一页就取前20条,第二页取21~40条,这里我们用
select top 当前页*每页记录数 * from 表A where 主键字段 not in (select top (当前页-1)*每页记录数 主键字段 from 表A)
这样形式的语句来实现。因这种查询方式,要用到主键,我们把它叫做“主键分页”。
--------------------------------------------------------------------------------
下面我们就这两种方式所用的sql语句的执行效率比较一下。
环境:奔M1.8
内存:1G
数据库:sql server2000
数据量:约200万条
语句1:
select getdate()
select * from f6_7xic
select getdate()
记录数:1969152 行
(10次平均值)
CPU占用率:100%
查询时间:22秒
语句2:
select getdate()
select top 20 * from f6_7xic where id not in ( select top 30000 id from f6_7xic )
select getdate()
(10次平均值)
CPU点用率:24%左右
查询时间:0.2秒
可见,主键分页在处理海量数据方面,效率是非常高的,也是首选。
--------------------------------------------------------------------------------
对于一个完整的分页,应当包括总记录数、总页数、当前页数、当前页、每页记录数、向前、向后、跳转等。所以,无论是指针分页,还是主键分页,还得传递一个类似 select count(*) as 记录总数 from 表名 这样的语句,从而获得记录数。
显然,主键分页是首选,但是他的写法太复杂,太麻烦,又何况对于联合查询、多表查询等情况,这个sql语句的写法,会更加复杂,会更加花费我们有限的大脑细胞。所以,得到一种通用,同时不需要写那么复杂的sql语句的程序,同时解决普通查询和海量查询的分页很有必要。时代在呼吁,人们在期待!