假设当前是第pageno页,每页有pagesize条记录,现在分别用mysql、oracle和sql server分页查询student表。
1、mysql的分页查询:
1 select 2 * 3 from 4 student 5 limit (pageno - 1) * pagesize,pagesize;
理解:(limit n,m) =>从第n行开始取m条记录,n从0开始算。
2、oracel的分页查询:
1 select 2 * 3 from 4 ( 5 select 6 s.*, rownum rn 7 from 8 (select * from student) s 9 where 10 rownum <= pageno * pagesize 11 ) 12 where 13 rn > (pageno - 1) * pagesize
或者
1 select 2 * 3 from 4 ( 5 select 6 s.*, rownum rn 7 from 8 (select * from student) s 11 ) 12 where 13 rn between (pageno - 1) * pagesize and pageno * pagesize
理解:假设pageno = 1,pagesize = 10,先从student表取出行号小于等于10的记录,然后再从这些记录取出rn大于0的记录,从而达到分页目的。rownum从1开始。
分析:对比这两种写法,绝大多数的情况下,第一个查询的效率比第二个高得多。
这是由于cbo 优化模式下,oracle可以将外层的查询条件推到内层查询中,以提高内层查询的执行效率。对于第一个查询语句,第二层的查询条件where rownum <=
pageno * pagesize就可以被oracle推入到内层查询中,这样oracle查询的结果一旦超过了rownum限制条件,就终止查询将结果返回了。
而第二个查询语句,由于查询条件between (pageno – 1) * pagesize and pageno * pagesize是存在于查询的第三层,而oracle无法将第三层的查询条件推到最内层(即使推到最内层也没有意义,因为最内层查询不知道rn代表什么)。因此,对于第二个查询语句,oracle最内层返回给中间层的是所有满足条件的数据,而中间层返回给最外层的也是所有数据。数据的过滤在最外层完成,显然这个效率要比第一个查询低得多。
3、sql server分页查询:
1 select 2 top pagesize * 3 from 4 ( 5 select 6 row_number () over (order by id asc) rownumber ,* 7 from 8 student 9 ) a 10 where 11 a.rownumber > (pageno - 1) * pagesize
理解:假设pageno = 1,pagesize = 10,先按照student表的id升序排序,rownumber作为行号,然后再取出从第1行开始的10条记录。
分页查询有的数据库可能有几种方式,这里写的可能也不是效率最高的查询方式,但这是我用的最顺手的分页查询,如果有兴趣也可以对其他的分页查询的方式研究一下。