分页查询格式:
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
以下是我的一个测试小例子
<%@ page language="java" import="java.sql.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>oracle分页原理</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<table>
<tr>
<td>
name
</td>
<td>
sal
</td>
</tr>
<%
String s_pageNo = request.getParameter("pageNo");
int pageNo = 1; //返回当前页数,默认为第一页
int rowCount = 0; //记录条数
int pageSize = 5; //每页显示条数
int pageCount = 0; //页数
if(s_pageNo != null){
pageNo = Integer.parseInt(s_pageNo);
}
Connection conn = null;
Statement st = null;
ResultSet rs = null;
String url = "jdbc:oracle:thin:@localhost:1521:数据库名";
String username = "scott";
String password = "tiger";
String sql = "select * from (select A.*,rownum rn from (select * from emp) A where rownum <= "+pageNo*pageSize+") where rn>="+((pageNo-1)*pageSize+1)+"";
String sql2 = "select * from (select A.*,rownum rn from (select * from emp) A where rn>="+((pageNo-1)*pageSize+1)+" and rn<="+pageNo*pageSize;
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
conn = DriverManager.getConnection(url, username, password);
st = conn.createStatement();
rs = st.executeQuery("select count(*) from emp");
if(rs.next()){
rowCount = rs.getInt(1);
if(rowCount%pageSize == 0){
pageCount = rowCount/pageSize;
}else {
pageCount = rowCount/pageSize + 1;
}
}
rs = st.executeQuery(sql2);
while (rs.next()) {
out.println("<tr>");
out.println("<td>" + rs.getString("ename") + "</td>");
out.println("<td>" + rs.getString("sal") + "</td>");
out.println("</tr>");
}
for(int i=1; i<=pageCount; i++){
out.print("<a href=index.jsp?pageNo=" +i+">" + i + "</a>");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
rs.close();
st.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
%>
</table>
</body>
</html>
分享到:
相关推荐
Oracle 分页查询优化与排序解决方案 本文主要解决 Oracle 分页查询中排序与效率问题,通过实践和分析,提供了两种解决方案,并对比了两种方法的优缺点。 知识点 1: Oracle 分页查询的基本概念 Oracle 分页查询是...
一、Oracle分页原理 Oracle提供了几种不同的分页方式,包括ROWNUM、ROWNUM BETWEEN、ROWNUMBER() OVER()等。其中,ROWNUM是最基础的分页方法,它为每一行返回的结果集分配一个唯一的整数值。但是,ROWNUM在并行查询...
### Oracle分页查询详解 #### 一、分页查询的重要性 在数据库操作中,分页查询是一项非常重要的技术。尤其当处理大量数据时,一次性获取所有数据不仅会消耗大量的网络带宽,还可能导致前端页面加载缓慢,用户体验...
### Oracle 分页查询并返回总记录数据存储过程 在数据库应用开发中,为了提高用户体验以及减少服务器负担,分页查询成为了一种常见的技术手段。Oracle 数据库提供了多种方法来实现分页查询,其中使用存储过程是一种...
在这个Oracle分页实例中,我们将探讨如何结合分页控件实现数据的分页显示。 首先,我们看到一个名为`webdiyer:AspNetPager`的控件,这是一个ASP.NET的Web分页控件。这个控件包含了几个关键属性: 1. `PageSize`:...
Oracle 分页查询详解 Oracle 分页查询是指从大型数据表中提取指定范围的记录,以便提高查询效率和减少数据传输量。常用的 Oracle 分页查询方法有三种:使用 ROWNUM、使用 ROW_NUMBER() 和使用子查询。 第一种方法...
根据所提供的信息,我们可以提炼出以下关于“ORACLE分页查询效率”的相关知识点: ### 一、Oracle中的分页查询 #### 1.1 分页查询的重要性 - **背景介绍**:在实际应用中,数据库查询结果往往非常庞大,一次性加载...
oracle分页存储过程,oracle分页存储过程
总结来说,Oracle分页存储过程是通过动态构造SQL语句,结合输入的分页参数,计算出总页数,并返回指定页的数据。这种方式在处理大量数据时提高了效率,同时也提供了灵活的查询控制。通过包装这些逻辑在存储过程中,...
本篇文章将深入探讨Oracle分页的机制,并提供易于理解的示例。 首先,我们来看SQL标准的`OFFSET-FETCH`和`LIMIT`子句。虽然`LIMIT`不是Oracle的原生语法,但Oracle 12c引入了`FETCH FIRST n ROWS ONLY`和`OFFSET m ...
"Oracle分页存储过程 终极版"旨在提供一个高效、灵活的解决方案,以应对各种分页查询的需求。这个存储过程优化了性能,并支持各种条件筛选和排序,使得在海量数据中进行分页操作变得更为便捷。 首先,理解分页的...
### Oracle分页存储过程解析与应用 在数据库管理和应用程序开发中,处理大量数据时,分页查询是一项常用且重要的技术。Oracle数据库提供了多种方法来实现数据分页,其中使用存储过程进行分页是一种高效且灵活的方式...
总的来说,"spring+ibatis+oracle分页缓存源码"项目展示了如何在Spring管理的环境中,利用iBatis和Oracle数据库实现高效的数据分页和缓存策略。通过理解和实践这些技术,开发者可以构建出更加健壮、响应快速的Web...
### Oracle分页查询详解 在Oracle数据库中,实现分页查询是常见的需求之一。通过合理的分页查询可以提高数据检索的效率,优化用户体验。本文将详细介绍一个特定的Oracle分页查询语句:“`select * from (select a.*...
在“ssh+oracle分页”这个主题中,我们将深入探讨如何利用这三个框架与Oracle数据库进行集成,并实现数据的分页显示。 1. **Struts框架**:Struts是一个基于MVC(Model-View-Controller)设计模式的Java Web框架。...
msql和oracle分页查询语句笔记
### Oracle分页详解 在数据库应用开发中,为了提高用户体验并优化系统性能,分页查询是一种常见的技术手段。本文将详细介绍如何在Oracle数据库中实现高效、灵活的分页功能。 #### 一、Oracle分页原理 Oracle中的...