Oracle分页查询性能优化及一些规则
1.一个分页查询语句引发的思考
2.优化分析过程
3.Rowid和Rownum的区别
4.多表关联查询对比
5.SQL优化常用规则
1.一个分页语句引发的思考
执行计划显示耗时是2.491秒,这是Oracle预估时间,实际在PL/SQL中的执行时间是大于20s。
![](/assets/blank.gif)
2.优化分析过程
全表查询单列进行排序与对全列进行排序的效率对比
运用单列排序分页
![](/assets/blank.gif)
3.Rownum和Rowid的区别
Rownum 是逻辑地址。表示查询某条记录在整个结果集中的位置,同一条记录查询条件不同对应的rownum是不同的而 rowid是不会变的。
Rowid是物理地址。用于定位数据表中某条数据的位置,是唯一的、不会改变,查询速度快。
4.优化分析过程
运用rowid单列排序分页
PL/SQL实际执行时间平均为1s左右
5.多表关联查询对比
收款单列表查询原SQL
SELECT *FROM (SELECT A.*, ROWNUM RFROM (select frs.*, fc.ERP_COMPANY_IDfrom (SELECT FR.*FROM FIN_RECEIPT FRWHERE FR.IS_DELETE = 0AND FR.VALID = 'T'AND FR.STATUS = '20'AND INSTR(FR.PAYER, '河北') > 0order by FR.RECEIPT_DATE DESC) frsLEFT JOIN FIN_COMPANY FCON frs.RECEIPTER_ID = fc.PKIDand fc.is_delete = 0) AWHERE ROWNUM <= 1200) BWHERE R > 0;
PL/SQL执行平均(连续执行取平均值)耗时:2.6s
收款单列表查询修改后SQL
SELECT t.*, fcom.ERP_COMPANY_IDFROM fin_receipt tLEFT JOIN FIN_COMPANY fcomON t.RECEIPTER_ID = fcom.PKIDwhere t.rowid in (select ridfrom (SELECT A.rid, ROWNUM RFROM (select frs.*,fc.ERP_COMPANY_IDfrom (SELECT FR.rowid rid,FR.RECEIPTER_ID,FR.IS_DELETE,FR.VALID,FR.STATUS,FR.RECEIPT_DATE,FR.receipt_No,FR.PAYER_ID,FR.PAYER,FR.BIZ_TYPE_ID,FR.AVAILABLE_AMOUNTFROM FIN_RECEIPT FRwhere FR.IS_DELETE = 0AND FR.VALID = 'T'AND FR.STATUS = '20'and FR.AVAILABLE_AMOUNT = 0AND INSTR(FR.PAYER, '河北') > 0order by FR.RECEIPT_DATE DESC) FRSLEFT JOIN FIN_COMPANY FCON frs.RECEIPTER_ID = fc.PKIDand fc.is_delete = 0) AWHERE ROWNUM <= 1200) Bwhere r > 0)order by t.RECEIPT_DATE DESC;
执行计划运行结果
PL/SQL执行平均(连续执行取平均值)耗时:2.0s
SQL优化常用规则
(1)选择最有效率的表名顺序(只在基于规则的优化器中有效)。
ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表(基础表 driving table)将被最先处理,在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表。如果有3个以上的表连接查询,那就需要选择交叉表(intersection table)作为基础表,交叉表是指那个被其他表所引用的表。
(2)WHERE子句中的连接顺序。
ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前,那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾。
(3)SELECT子句中避免使用 “*” 。
ORACLE在解析的过程中,会将“*”依次转换成所有的列名,这个工作是通过查询数据字典完成的,这意味着将耗费更多的时间。
(4)减少访问数据库的次数。
ORACLE在内部执行了许多工作:解析SQL语句,估算索引的利用率、绑定变量、读数据块等。
(5)通过内部函数提高SQL效率。
复杂的SQL往往牺牲了执行效率。能够掌握上面的运用函数解决问题的方法在实际工作中是非常有意义的。
(6)使用表的别名(Alias)。
当在SQL语句中连接多个表时,请使用表的别名并把别名前缀于每个Column上,这样一来,就可以减少解析的时间并减少那些由Column歧义引起的语法错误。
(7)用EXISTS替代IN、用NOT EXISTS替代NOT IN。
在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接。在这种情况下,使用EXISTS(或NOT EXISTS)通常将提高查询的效率。 在子查询中,NOT IN子句将执行一个内部的排序和合并。无论在哪种情况下,NOT IN都是最低效的 (因为它对子查询中的表执行了一个全表遍历)。为了避免使用NOT IN,我们可以把它改写成外连接(Outer Join)或NOT EXISTS。
例子:
(高效)
SELECT * FROM EMP (基础表)
WHERE EMPNO > 0 AND EXISTS (SELECT ‘X’ FROM DEPT WHERE DEPT.DEPTNO = EMP.DEPTNO AND LOC = ‘MELB’)
(低效)
SELECT * FROM EMP (基础表)
WHERE EMPNO > 0 AND DEPTNO IN(SELECT DEPTNO FROM DEPT WHERE LOC = ‘MELB’)
(6)用索引提高效率。
索引是表的一个概念部分,用来提高检索数据的效率,ORACLE使用了一个复杂的自平衡B-tree结构。通常,通过索引查询数据比全表扫描要快。当ORACLE找出执行查询和Update语句的最佳路径时,ORACLE优化器将使用索引。
同样在联结多个表时使用索引也可以提高效率。另一个使用索引的好处是,它提供了主键(primarykey)的唯一性验证。那些LONG或LONG RAW数据类型,你可以索引几乎所有的列。通常,在大型表中使用索引特别有效。当然,你也会发现,在扫描小表时,使用索引同样能提高效率。
虽然使用索引能得到查询效率的提高,但是我们也必须注意到它的代价。索引需要空间来存储,也需要定期维护,每当有记录在表中增减或索引列被修改时,索引本身也会被修改。这意味着每条记录的INSERT、DELETE、UPDATE将为此多付出4、5次的磁盘I/O。因为索引需要额外的存储空间和处理,那些不必要的索引反而会使查询反应时间变慢。定期的重构索引是有必要的。
(7)用EXISTS替换DISTINCT:
当提交一个包含一对多表信息(比如部门表和雇员表)的查询时,避免在SELECT子句中使用DISTINCT。 一般可以考虑用EXIST替换,EXISTS 使查询更为迅速,因为RDBMS核心模块将在子查询的条件一旦满足后,立刻返回结果。
例子:
(低效):
SELECT DISTINCT DEPT_NO,DEPT_NAME
FROM DEPT D , EMP E
WHERE D.DEPT_NO = E.DEPT_NO
(高效):
SELECT DEPT_NO,DEPT_NAME FROM DEPT D
WHERE EXISTS ( SELECT ‘X' FROM EMP E WHERE E.DEPT_NO = D.DEPT_NO);
(8)避免使用耗费资源的操作。
带有DISTINCT、UNION、MINUS、INTERSECT、ORDER BY的SQL语句会启动SQL引擎执行耗费资源的排序(SORT)功能。DISTINCT需要一次排序操作,而其他的至少需要执行两次排序。通常,带有UNION、MINUS、INTERSECT的SQL语句都可以用其他方式重写。如果你的数据库的SORT_AREA_SIZE调配得好,使用UNION、MINUS、INTERSECT也是可以考虑的,毕竟它们的可读性很强。
(9)sql语句用大写的。
因为oracle总是先解析sql语句,把小写的字母转换成大写的再执行。
(10)在java代码中尽量少用连接符“+”连接字符串!
(11)避免在索引列上使用NOT。
我们要避免在索引列上使用NOT,NOT会产生和在索引列上使用函数相同的影响。当ORACLE遇到NOT时,会停止使用索引转而执行全表扫描。
(12)避免在索引列上使用计算。
WHERE子句中,如果索引列是函数的一部分。优化器将不使用索引而使用全表扫描。
例子:
低效:
SELECT … FROM DEPT WHERE SAL * 12 > 25000;
高效:
SELECT … FROM DEPT WHERE SAL > 25000/12;
(13)用>=替代>
例子:
高效:
SELECT * FROM EMP WHERE DEPTNO >=4
低效:
SELECT * FROM EMP WHERE DEPTNO >3
两者的区别在于, 前者DBMS将直接跳到第一个DEPT等于4的记录而后者将首先定位到DEPTNO=3的记录并且向前扫描到第一个DEPT大于3的记录.
Oracle分页查询性能优化及一些规则相关推荐
- Oracle分页查询性能优化
对于数据库中表的数据的 Web 显示,如果没有展示顺序的需要,而且因为满足条件的记录如 此之多,就不得不对数据进行分页处理.常常用户并不是对所有数据都感兴趣的,或者大部分情 况下,他们只看前几页. 通 ...
- Oracle 模糊查询性能优化
问题:使用like模糊查询,性能不是很好,寻求更高效的模糊查询的方法 解决:使用oracle自带的instr()函数解决 参考:https://blog.csdn.net/u010028869/art ...
- oracle 亿级数据分页,oracle分页查询千万级优化-Oracle
oracle分页查询千万级优化,在做比对项目时,有表是3千万多的数据,在页面做分页查询时很卡40s,反正差不多一分钟的时间,后来更了sql,优化了代码就好了很多,4s就可以了. 代码里优化是把总条数存 ...
- mysql笔记03 查询性能优化
查询性能优化 1. 为什么查询速度会慢? 1). 如果把查询看作是一个任务,那么它由一系列子任务组成,每个子任务都会消耗一定的时间.如果要优化查询,实际上要优化其子任务,要么消除其中一些子任务,要么减 ...
- Oracle 数据库的性能优化
oracle数据库的性能优化 对于ORACLE数据库的数据存取,主要有四个不同的调整级别,第一级调整是操作系统级包括硬件平台,第二级调整是ORACLE RDBMS级的调整,第三级是数据库设计级的调整, ...
- Sql Server查询性能优化之索引篇【推荐】
Sql Server查询性能优化之索引篇[推荐] 这篇是索引系列中比较完整的,经过整理而来的 一 索引基础知识 索引概述 1.概念 可以把索引理解为一种特殊的目录.就好比<新华字典>为了加 ...
- MySQL系列-- 4. 查询性能优化
4. 查询性能优化 4.1 为什么查询速度会变慢 快速查询取决于响应时间 如果把查询看成是一个任务,那么它由一系列子任务组成,每个子任务都会消耗一定的时间.如果要优化查询,实际上要优化其子任务,要么消 ...
- Oracle 分页查询的高效写法
最近遇到了这个问题,整理下Oracle 分页查询的高效写法 一. 低效与高效写法对比 低效的写法 select column_lists from (select rownum as rn,A.* ...
- oracle分页查询sql语句通用,oracle分页查询sql语句,oracle分页查询sql语句详解
oracle分页查询sql语句,oracle分页查询sql语句详解,Oracle分页查询sql语句 Oracle中分页和MySql中的分页不同,MySql中的分页使用关键字limit即可,相对简单一点 ...
最新文章
- 为什么校招面试中总被问“线程与进程的区别”?我该如何回答?
- 用protoc-gen-lua生成PB的lua代码
- Java基础面试题与答案
- Apache Maven 3.0.3 (yum) 安裝 (CentOS 6.4 x64)
- java8-Optional
- linux7ip路由,Centos7源地址访问路由(双IP双网关配置)
- vc++ 类 定时器api_关于JS中一些重要的api实现, 巩固你的原生JS功底
- 关于修改esp8266波特率sscom32串口调试窗口没反应解决方案
- java 注入为空_Spring @Autowired 注入为 null
- blender 快捷键
- 【脑洞大开】智慧海洋网课答案
- ISBN书号怎么查询
- Fixture证书权限导致CSR申请证书失败的问题 [已解决]
- 2021年道路运输企业主要负责人模拟考试题库及道路运输企业主要负责人实操考试视频
- Word中如何设置毕业论文每章节不同页眉
- 学计算机的上升路线,学习计算机路线图.doc
- 风变科技python课程评价.11_风变科技在线职业教育课程不错,菜鸟也能成python高手...
- 2020 Ansys Lumerical FDTD MODE安装步骤说明
- linux下dev目录的作用,Android/Linux根目录下常见目录作用
- PyAutoGUI帮助文档