日期:2014-05-16  浏览次数:20360 次

Oracle数据库中的分页语句
方式一:
SELECT * FROM
(
SELECT A.*, ROWNUM RN
FROM (SELECT * FROM TABLE_NAME) A
)
WHERE RN BETWEEN 3*(3-1)+1 AND 3*3

方式二分页查询格式:

SELECT * FROM
(
SELECT A.*, ROWNUM RN
FROM (SELECT * FROM TABLE_NAME ORDER BY VALUE) A
WHERE ROWNUM <= 20*2
)
WHERE RN >20*(2-1)

对比这两种写法,绝大多数的情况下,第一个查询的效率比第二个高得多。

这是由于CBO优化模式下,Oracle可以将外层的查询条件推到内层查询中,以提高内层查询的执行效率。对于第一个查询语句,第二层的查询条件WHERE ROWNUM <= 40就可以被Oracle推入到内层查询中,这样Oracle查询的结果一旦超过了ROWNUM限制条件,就终止查询将结果返回了。

而第二个查询语句,由于查询条件BETWEEN 21 AND 40是存在于查询的第三层,而Oracle无法将第三层的查询条件推到最内层(即使推到最内层也没有意义,因为最内层查询不知道RN代表什么)。因此,对于第二个查询语句,Oracle最内层返回给中间层的是所有满足条件的数据,而中间层返回给最外层的也是所有数据。数据的过滤在最外层完成,显然这个效率要比第一个查询低得多。

上面分析的查询不仅仅是针对单表的简单查询,对于最内层查询是复杂的多表联合查询或最内层查询包含排序的情况一样有效。

这里就不对包含排序的查询进行说明了,下一篇文章会通过例子来详细说明。下面简单讨论一下多表联合的情况。对于最常见的等值表连接查询,CBO一般可能会采用两种连接方式NESTED LOOP和HASH JOIN(MERGE JOIN效率比HASH JOIN效率低,一般CBO不会考虑)。在这里,由于使用了分页,因此指定了一个返回的最大记录数,NESTED LOOP在返回记录数超过最大值时可以马上停止并将结果返回给中间层,而HASH JOIN必须处理完所有结果集(MERGE JOIN也是)。那么在大部分的情况下,对于分页查询选择NESTED LOOP作为查询的连接方法具有较高的效率(分页查询的时候绝大部分的情况是查询前几页的数据,越靠后面的页数访问几率越小)。

如果不介意在系统中使用HINT的话,可以将分页的查询语句改写为:

SELECT /*+ FIRST_ROWS */ * FROM
(
SELECT A.*, ROWNUM RN
FROM (SELECT * FROM TABLE_NAME) A
WHERE ROWNUM <= 40
)
WHERE RN >= 21


使用row_number()高效分页
SELECT T.* FROM(
SELECT S.*,ROW_NUMBER() OVER(ORDER BY VALUE) AS NUM
FROM TABLENAME S
) T
WHERE NUM BETWEEN 3*(1-1)+1 AND 3*1

还有使用Minus关键字实现分页:
select * from studybook where rownum<=3*2
minus
select * from studybook where rownum<=3*(2-1)

*********************************************************************************

Mysql分页采用limt关键字

select * from t_order limit 5,10; #返回第6-15行数据
select * from  t_order limit  5; #返回前5行
select * from  t_order limit  0,5; #返回前5行

Mssql 2000分页采用top关键字(20005以上版本也支持关键字rownum)

Select top 10 * from t_order where id not in (select id from t_order where id>5 ); //返回第6到15行数据

其中10表示取10记录 5表示从第5条记录开始取