`
huangzhaorongit
  • 浏览: 26190 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

ORACLE大数据量下的分页解决方法

阅读更多
一般用截取ID方法,还有是三层嵌套方法.

一种分页方法 :
  <%
int i=1;
int numPages=14;
String pages = request.getParameter("page") ;
int currentPage = 1;
currentPage=(pages==null)?(1):{Integer.parseInt(pages)}
sql = "select count(*) from tables";
ResultSet rs = DBLink.executeQuery(sql) ;
while(rs.next()) i = rs.getInt(1) ;
int intPageCount=1;
intPageCount=(i%numPages==0)?(i/numPages):(i/numPages+1);
int nextPage ;
int upPage;
nextPage = currentPage+1;
if (nextPage>=intPageCount) nextPage=intPageCount;
upPage = currentPage-1;
if (upPage<=1) upPage=1;
rs.close();
sql="select * from tables";
rs=DBLink.executeQuery(sql);
i=0;
while((i<numPages*(currentPage-1))&&rs.next()){i++;}
%>
//输出内容
//输出翻页连接
合计:<%=currentPage%>/<%=intPageCount%><a href="List.jsp?page=1">第一页</a><a

href="List.jsp?page=<%=upPage%>">上一页</a>
<%
for(int j=1;j<=intPageCount;j++){
if(currentPage!=j){
%>
<a href="list.jsp?page=<%=j%>">[<%=j%>]</a>
<%
}else{
out.println(j);
}
}
%>
<a href="List.jsp?page=<%=nextPage%>">下一页</a><a href="List.jsp?page=<%=intPageCount%>">最后页



</a>

-------------------------------------------------



(一)分页实现及性能

Oracle的分页查询语句基本上可以按照本文给出的格式来进行套用。



分页查询格式:

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

其中最内层的查询SELECT * FROM TABLE_NAME表示不进行翻页的原始查询语句。ROWNUM <= 40和RN >= 21控制分页查询的每页的范围。

上面给出的这个分页查询语句,在大多数情况拥有较高的效率。分页的目的就是控制输出结果集大小,将结果尽快的返回。在上面的分页查询语句中,这种考虑主要体现在WHERE ROWNUM <= 40这句上。

选择第21 到40条记录存在两种方法,一种是上面例子中展示的在查询的第二层通过ROWNUM <= 40来控制最大值,在查询的最外层控制最小值。而另一种方式是去掉查询第二层的WHERE ROWNUM <= 40语句,在查询的最外层控制分页的最小值和最大值。这是,查询语句如下:

SELECT * FROM
(
SELECT A.*, ROWNUM RN
FROM (SELECT * FROM TABLE_NAME) A
)
WHERE RN BETWEEN 21 AND 40

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

这是由于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

(二)Oracle Top n

SELECT A.*, ROWNUM RN
FROM (SELECT * FROM TABLE_NAME) A
WHERE ROWNUM <= 40

以上是oracle 实现top n的功能

SELECT A.*, ROWNUM RN
FROM (SELECT * FROM TABLE_NAME) A
WHERE ROWNUM between 2 and 100

总是返回空记录

原因:

对于rownum来说它是oracle系统顺序分配为从查询返回的行的编号,返回的第一行分配的是1,第二行是2,依此类推,这个伪字段可以用于限制查询返回的总行数,而且rownum不能以任何表的名称作为前缀。
举例说明:
例如表:student(学生)表,表结构为:
ID       char(6)      --学号
name    VARCHAR2(10)   --姓名
create table student (ID char(6), name VARCHAR2(100));
insert into sale values('200001',‘张一’);
insert into sale values('200002',‘王二’);
insert into sale values('200003',‘李三’);
insert into sale values('200004',‘赵四’);
commit;
(1) rownum 对于等于某值的查询条件
如 果希望找到学生表中第一条学生的信息,可以使用rownum=1作为条件。但是想找到学生表中第二条学生的信息,使用rownum=2结果查不到数据。因 为rownum都是从1开始,但是1以上的自然数在rownum做等于判断是时认为都是false条件,所以无法查到rownum = n(n>1的自然数)。
SQL> select rownum,id,name from student where rownum=1;(可以用在限制返回记录条数的地方,保证不出错,如:隐式游标)
SQL> select rownum,id,name from student where rownum=1;
    ROWNUM ID     NAME
---------- ------ ---------------------------------------------------
         1 200001 张一
SQL> select rownum,id,name from student where rownum =2;
    ROWNUM ID     NAME
---------- ------ ---------------------------------------------------
(2)rownum对于大于某值的查询条件
   如果想找到从第二行记录以后的记录,当使用rownum>2是查不出记录的,原因是由于rownum是一个总是从1开始的伪列,Oracle 认为rownum> n(n>1的自然数)这种条件依旧不成立,所以查不到记录
SQL> select rownum,id,name from student where rownum >2;
ROWNUM ID     NAME
---------- ------ ---------------------------------------------------
那如何才能找到第二行以后的记录呀。可以使用以下的子查询方法来解决。注意子查询中的rownum必须要有别名,否则还是不会查出记录来,这是因为rownum不是某个表的列,如果不起别名的话,无法知道rownum是子查询的列还是主查询的列。
SQL>select * from(select rownum no ,id,name from student) where no>2;
        NO ID     NAME
---------- ------ ---------------------------------------------------
         3 200003 李三
         4 200004 赵四
SQL> select * from(select rownum,id,name from student)where rownum>2;
    ROWNUM ID     NAME
---------- ------ ---------------------------------------------------
(3)rownum对于小于某值的查询条件
如果想找到第三条记录以前的记录,当使用rownum<3是能得到两条记录的。显然rownum对于rownum<n((n>1的自然数)的条件认为是成立的,所以可以找到记录。
SQL> select rownum,id,name from student where rownum <3;
    ROWNUM ID     NAME
---------- ------ ---------------------------------------------------
        1 200001 张一
        2 200002 王二
综 上几种情况,可能有时候需要查询rownum在某区间的数据,那怎么办呀从上可以看出rownum对小于某值的查询条件是人为true的,rownum对 于大于某值的查询条件直接认为是false的,但是可以间接的让它转为认为是true的。那就必须使用子查询。例如要查询rownum在第二行到第三行之 间的数据,包括第二行和第三行数据,那么我们只能写以下语句,先让它返回小于等于三的记录行,然后在主查询中判断新的rownum的别名列大于等于二的记 录行。但是这样的操作会在大数据集中影响速度。
SQL> select * from (select rownum no,id,name from student where rownum<=3 ) where no >=2;
        NO ID     NAME
---------- ------ ---------------------------------------------------
         2 200002 王二
         3 200003 李三
(4)rownum和排序
Oracle中的rownum的是在取数据的时候产生的序号,所以想对指定排序的数据去指定的rowmun行数据就必须注意了。
SQL> select rownum ,id,name from student order by name;
    ROWNUM ID     NAME
---------- ------ ---------------------------------------------------
         3 200003 李三
         2 200002 王二
         1 200001 张一
         4 200004 赵四
可以看出,rownum并不是按照name列来生成的序号。系统是按照记录插入时的顺序给记录排的号,rowid也是顺序分配的。为了解决这个问题,必须使用子查询
SQL> select rownum ,id,name from (select * from student order by name);
    ROWNUM ID     NAME
---------- ------ ---------------------------------------------------
         1 200003 李三
         2 200002 王二
         3 200001 张一
         4 200004 赵四
这样就成了按name排序,并且用rownum标出正确序号(有小到大)

--- 以上为rownum的必学处,为了更好地使用rownum打下基础。

其 实, 理解rownum的关键是Oracle 如何执行查询语句. 如果先执行笛卡尔集运算,再执行where条件限制,那么rownum就可以实现 rownum> n(n>=1)的功能. 但oralce是边执行笛卡尔集运算,边应用选择条件,所以rownum>n(n>1=)永远不成立 ( 网友评论 )

--- 自我练习, 嘿嘿 表: BOOKS

select rownum,isbn,title,price from (select * from BOOKS order by price desc);

select *
  from (select rownum ro,b.* from BOOKS b where rownum < 10)
where ro > 5;

select * from BOOKS where rownum < 10;

select *
   from (select b.*,
                rownum ro
           from BOOKS b
          where rownum < 20
        )
  where ro > 10;
 
  select *
    from (select *
            from BOOKS
            order by TITLE
         )
  where rownum > 8;
 
  select *
    from (select rownum ro,b.*
            from BOOKS b
            order by b.TITLE
         )
  where ro > 8;
 
  select *
    from (select rownum ro,f.*
            from (select *
                    from BOOKS b
                    order by b.title
                 ) f
         )
  where ro > 8 ;


分享到:
评论

相关推荐

    解决Oracle分页查询中排序与效率问题

    在Oracle数据库中进行分页查询时,经常会出现性能瓶颈,尤其是在处理大数据量的情况下。本篇文章将详细探讨如何优化Oracle分页查询中的排序与效率问题。 #### 一、理解Oracle分页查询的基本原理 在Oracle中实现...

    Oracle 3种分页SQL方法比较

    这种方法既支持ORDER BY,又避免了全表扫描和子查询,因此在大数据量分页时可能更为高效。 总结来说,ROWNUM是最基础的分页方式,适合小数据量或无需排序的情况;ROWNUM结合子查询能保证有序分页,但效率较低;...

    java web与Oracle数据的分页功能

    本项目提供的源代码正是针对这一需求,提供了在Java Web环境中利用Oracle数据库实现分页功能的解决方案。 首先,我们来理解一下分页的基本概念。分页是将数据库查询结果分成若干页展示,用户可以逐页浏览,而不是一...

    Oracle分页(limit方式的运用)

    在数据库查询操作中,分页是非常常见的需求之一,尤其是在数据量较大的情况下,为了提高用户体验以及减轻服务器压力,我们需要将数据分成若干个页面进行展示。Oracle数据库作为业界广泛使用的数据库系统之一,在实现...

    Oracle的SQL分页实践

    这对于提高用户体验和优化系统性能至关重要,尤其是在处理大数据量的Web应用中。本实践将深入探讨Oracle SQL分页的实现方法。 首先,我们要了解Oracle中的基本分页查询方式。在Oracle 9i及更高版本中,可以使用...

    大数据量翻页查询的一点经验

    在大数据量的翻页查询中,优化查询性能是至关重要的,因为这直接影响到系统的响应速度和用户体验。在本文中,我们将探讨如何针对特定场景优化这种查询。首先,我们需要理解系统的基本设定:每天生成一张包含1000万条...

    Oracle&JSP分页和Oracle分页

    另一种更高效的方法是使用Oracle的`ROW_NUMBER()`函数,配合`OVER()`子句,这样可以实现更复杂的分页逻辑。比如,如果我们要查询第5页的数据,每页20条,可以这样写: ```sql SELECT * FROM ( SELECT ROW_NUMBER()...

    使用Oracle数据库时的Web分页方法

    首先,一个理想的分页方案应该满足两个主要要求:1) 减少数据库处理的数据量;2) 减小数据库与Web应用服务器之间传输的数据量。这两个要求对于性能优化至关重要,因为它们直接影响到查询速度和网络带宽使用。 以一...

    oracle 分页完整代码

    同时,对于大数据量的场景,还可以考虑使用Oracle的分页功能,如RANGE BETWEEN或者Oracle 12c引入的FETCH FIRST子句,这些方法可以更高效地处理分页。 此外,对于Java应用,可以使用ORM框架如Hibernate或MyBatis来...

    oracle 分页类文件

    Oracle数据库在处理大数据量时,分页查询是必不可少的功能,它可以有效地提高数据检索效率,减少内存占用,并提供更好的用户体验。本文件包包含了一系列用于实现Oracle数据库分页查询的类,帮助开发者解决分页问题。...

    JAVA_JDBC面向对象分页(初步设计二之oracle)

    在处理大量数据时,分页查询是一种有效的策略,可以提高应用程序的性能,避免一次性加载过多数据导致内存压力。Oracle数据库作为一款广泛使用的商业数据库系统,经常在企业级应用中被采用。本篇文章将重点讨论如何...

    Oracle 分页实例 带分页控件用法

    Oracle数据库在处理大数据量时,分页查询是必不可少的功能,它可以有效地提高网页或应用程序的加载速度,减少不必要的数据传输,提升用户体验。在这个Oracle分页实例中,我们将探讨如何结合分页控件实现数据的分页...

    Oracle的分页查询语句 Oracle分页的存储过程

    Oracle数据库在处理大数据量查询时,分页查询是一种常见的优化策略,目的是限制返回结果集的大小,加快查询速度,提供更好的用户体验。本文将详细探讨Oracle的分页查询语句及其存储过程。 首先,Oracle的分页查询...

    Oracle 存储过程分页

    在处理大量数据时,分页查询是必不可少的,它可以有效地减少网络传输的数据量,提高用户体验。Oracle 提供了多种方法实现分页查询,下面我们将详细探讨Oracle存储过程中的分页实现。 1. **ROWNUM伪列** 在早期的...

    kettle oracle循环分页迁移数据的完整例子,生成txt后FTP上传到远程服务器

    3. **循环分页查询**:在大数据量的场景下,一次性获取所有数据可能会导致性能问题,因此通常采用分页查询的方式来处理。Kettle中的“生成分页.ktr”可能就是实现这个功能的工作流,通过设置页码和每页大小来逐次...

    Oracle自定义数据分页存储过程

    Oracle数据库在处理大数据量时,为了提高查询效率和用户体验,常常需要实现数据的分页显示。自定义数据分页存储过程是一种有效的方法,它能够避免全表扫描,降低数据库资源消耗,同时提供灵活的查询条件。本文将详细...

    java实现oracle分页策略

    Oracle提供了多种分页方法,其中最常用的是ROWNUM和ROWNUM配合子查询或者连接查询。 在Java中,我们可以创建一个分页类,包含当前页码、每页记录数等属性,并提供计算起始位置和结束位置的方法。例如: ```java ...

    oracle分页查询sql

    基于`ROWNUM`的分页查询是Oracle中最常见的分页方法之一。它通过两层嵌套查询实现,具体格式如下: ```sql SELECT * FROM ( SELECT A.*, ROWNUM RN FROM ( SELECT * FROM TABLE_NAME ) A WHERE ROWNUM ) ...

    ORACLE分页查询效率

    - **合理设置分页大小**:过大的分页大小会导致单次查询的数据量过大,增加网络传输时间;过小的分页大小则会增加查询次数,增加数据库压力。 - **考虑使用分区表**:对于非常庞大的表,可以考虑使用分区表技术,将...

    SSH+ORACLE好用分页

    在这个场景下,"SSH+ORACLE好用分页"意味着我们将SSH框架与Oracle数据库结合,实现了高效的数据分页功能。 数据分页是Web应用中常见的需求,特别是在处理大量数据时,分页可以提高用户体验,避免一次性加载过多数据...

Global site tag (gtag.js) - Google Analytics