分页处理是在Web开发中经常遇到的问题,对于不同的分页方式,在负载较高的情况下会产生极大的性能差异,一般来说,分页的处理方式分为两种,一种是程序分页,即从数据库中取出记录集之后,使用循环截取的方式取得需要的数据,一种是通过数据库提供的分页功能即SQL的技巧来处理,后者在负载较高的情况下会提供良好的性能,尤其是在数据量较多的情况下,下面简单介绍一下这两种方式的实现
我使用一个示例表
create table student
(
id int not null primary key,
name varchar(20) not null ,
code varchar(20),
description varchar(100)
)
这个在不同的数据库中都可以实现,在Oracle中最好修改varchar 为varchar2
设定我们取第10页的数据,每页10行,即取91-100行的数据
1、程序分页
我们以ASP为例,
sql = “select * from student“
set rs = conn.execute(sql);
i=0;
Do until rs.eof or i>100
i=i+1
if i>90then
response.write rs.....
end if
rs.movenext
loop
这样做的问题就是每次要从数据库中取出所有数据,然后遍历,这样在压力大的时候会在数据库和应用服务器之间产生非常大的数据交互,尤其是取后面的数据时,效率极低
2、数据库分页
这种方式的处理优点是充分发挥数据库的优势,只取出需要的数据,下面介绍不同的数据库的处理方式
1)Oracle
在Oracle中我们利用rownum的特性来处理这类问题,如
select * from (
select rownum rid,a.*
from student a
)
where rid between 91 and 100
如果是复杂的SQL,我们只要在sql的select后面加上rownum id,然后在外层sql中使用类似的结构就可以了,要注意的是目标sql中的字段名不要和rid重复,如果想批量使用的话,可以采用一个冷门的字段。
一般来说,您可以将目标sql去掉select,这段字符串设为area_sql,然后
select * from (
select rownum rid,area_sql)
where rid between 91 and 100
还有另外一种方式处理这种问题,使用minus,如下
select * from student
where rownum<101
minux
select * from student
where rownum<91
采用minus的过率功能,这样的好处是更容易模块化、更通用,但效率稍低
在Asp中这么调用
set rs = conn.execute(sql);
do until rs.eof
reponse.write rs......
rs.movenext
loop
2)Sql Server
在SQL server中处理这种问题麻烦,因为sql server中没有提供伪列的功能,也没有筛选的功能,
所以想达到Oracle同样的效果,必须写存储过程来解决,而且没有通用性,需要对每个表书写存储过程,存储过程在这里就不介绍了,能产生一定效果的方法是
select top 100 *
from student
然后用程序分页的方法来处理问题,这样效率在取后面的数据效率也很低,在取前面数据的时候可以体现出优势
3)Mysql
Mysql 是一个开发源码数据库,速度较快,但缺乏很多必要的功能,但在小型web页面中已经够用了
它的分页系统处理问题如下
select *
from student
where .....
limit 90,10
limit函数是这样处理的,第一个参数是起始行,第二个参数为读取的行数,这样就取出了91-100行的数据,
Mysql的处理方式非常灵活,而且也容易模块化,只要修改起始行即可,
在php中如下
$rs = mysql_query(sql);
while($line = mysql_fetch_array($rs))
{
echo $line[...];
}