问题提出:
etl中有一过程qmsressummt0_test,用来抽取各地xxx应用的资料,目前处于测试阶段,暂时存放2个厂区一个月的测试资料,目前该过程执行一次要30分钟,按此状况,日后如再抽取其他厂区的资料,预计执行三个小时以上,小组开发人员请求协助优化。
优化前的执行情况
9:31:20 SQL> set serveroutput on;
9:31:25 SQL> exec qmsressummt0_test;
PL/SQL procedure successfully completed
10:00:54 SQL>
执行一次,耗时在30分钟
调优步骤:
步骤一:调整sql的优化器由rbo变为采用cbo方式
查看procedure涉及到table的统计信息,三个表都没有统计信息
10:33:35 SQL> select * from user_tables where table_name in ('QMS310T0','QMS311T0',UPPER('qmsressummt0'));
TABLE_NAME TABLESPACE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS AVG_SPACE
------------------------------ --------------------------- ---------- ------------ ----------
QMS310T0 QMSS
QMS311T0 QMSS
QMSRESSUMMT0 QMSS
Oracle9i,10g的sql优化器优先采用cbo方式,cbo方式下,oracle优化器可以更智能更合理的选择执行计划,从而使sql的执行效率更高,而若相关table和index没有统计信息的话,则会转而采用传统的rbo方式,在此例子中,任意查看过程中的某个sql,发现都是采用rbo。
接下来分析该过程涉及到的三个表,收集相关统计信息。
对这三个表做分析,收集统计信息
10:00:54 SQL> analyze table qms310t0 compute statistics for table for all indexes;
Table analyzed
10:33:11 SQL> analyze table qms311t0 compute statistics for table for all indexes;
Table analyzed
10:33:21 SQL> analyze table qmsressummt0 compute statistics for table for all indexes;
Table analyzed
10:33:35 SQL>
可以试验比对一下,采用rbo和cbo的执行效率对比情况
10:41:43 SQL> exec qmsressummt0_test;
PL/SQL procedure successfully completed
11:03:37 SQL>
可以发现,现在的执行时间在20分钟,在此过程中,效率提高了接近1/3,由此,我们可以看到相同的sql语句,优化器采用cbo比采用rbo效率要提高不少。
步骤二:合理利用索引,进一步提高sql执行效率
分析procedure和table,相关的表需要建立索引,这一步需要根据以往的经验,建立相关索引(开发人员并没有考虑新增索引,甚至主键都没有),并抽取sql语句,查看索引添加前后的执行计划,最终建立的索引(主键索引)如下
SQL> alter table QMS310t0
add constraint PK1_QMS310T0 primary key (BRANCH_NO, CHECK_NO,vend_id,mtrl_no)
Using Index tablespace indx;
Table altered
SQL> alter table QMS311t0
add constraint PK1_QMS311T0 primary key (BRANCH_NO, CHECK_NO, SAMPL_NO,mtrl_no, CHK_NO)
Using Index tablespace indx ;
Table altered
SQL>alter table qmsressummt0 add constraint pk_qmsresssummt0 primary key (yyyymm,branch_no,vend_id,mtrl_no,chk_no) using index tablespace indx;
Table altered
SQL> create index idx_qms310t0_ymd on qms310t0(yymmdd) tablespace indx;
Index created
再次执行过程
11:43:51 SQL> exec qmsressummt0_test;
PL/SQL procedure successfully completed
11:49:34 SQL>
时间大约为6分钟。
步骤三:合理的改变业务处理方式,亦可提高程序执行效率
对该过程的深入分析可以发现,其中的max最大值,min最小值,和count(*)三个sql语句可以合并成一个sql语句,这样同样可以达到减少sql的执行次数和数据块的io数量,提高效率和降低执行时间的目的。
修改前的sql语句 | 修改后的sql语句
select max(b.item_val) | select max(b.item_val),min(b.item_val),Count(*)
into v_chk_max | into v_chk_max,v_chk_min,v_cnt_01
from qms310t0 a, qms311t0 b | from qms310t0 a, qms311t0 b
where a.check_no = b.check_no | where a.check_no = b.check_no
and a.branch_no = b.branch_no | and a.branch_no = b.branch_no
and a.mtrl_no = r1.mtrl_no | and a.mtrl_no = r1.mtrl_no
and a.vend_id = r1.vend_id | and a.vend_id = r1.vend_id
and a.branch_no = r1.branch_no | and a.branch_no = r1.branch_no
and b.chk_no = r1.chk_no; | and b.chk_no = r1.chk_no;
|
select min(b.item_val) |
into v_chk_min |
from qms310t0 a, qms311t0 b |
where a.check_no = b.check_no |
and a.branch_no = b.branch_no |
and a.mtrl_no = r1.mtrl_no |
and a.vend_id = r1.vend_id |
and a.branch_no = r1.branch_no |
and b.chk_no = r1.chk_no; |
SELECT count(*) |
INTO v_cnt_01 |
FROM qms311t0 a, qms310t0 b |
WHERE a.branch_no = r1.branch_no |
AND a.mtrl_no = r1.mtrl_no |
AND a.chk_no = r1.chk_no |
and a.check_no = b.check_no |
and a.branch_no = b.branch_no; |
执行的情况:
15:31:13 SQL> exec qmsressummt0_test
PL/SQL procedure successfully completed
15:33:42 SQL>
最终,该过程执行的时间<3分钟。
至此,程序执行效率提高10倍左右,调整优化结束。
分享到:
相关推荐
所有的pl/sql都叫过程 创建存储过程: create or replace procedure p1 (v1 int ,v2 int)--存储过程的参数列表 as --声明局部变量 begin null; end; 调用过程 1.declare调用 2.命令调用 删除存储过程:drop ...
PL/SQL 基础,一个不错的 PL/SQL 参考手册。内容预览: ---- 第一章 PL/SQL 简介 ---- 1. Oracle应用编辑方法概览 1) Pro*C/C++/... : C语言和数据库打交道的方法,比OCI更常用; 2) ODBC 3) OCI: C语言和...
此文以oracle数据库中的SCOTT用户的EMP表为例,用PL/SQL Developer编写一个分页存储过程,要求是:可以输入表名,每页显示记录数,当前页,返回总记录数,总页数和返回的结果集。 由于需要返回查询出来的结果集,...
在 PL/SQL 开发过程中,使用 SQL、PL/SQL 可以实现大部分的需求,但是在某些特殊的情况下,在 PL/SQL 中使用标准的 SQL 语句或 DML 语句不能实现自己的需求,比如需要动态建表或某个不确定的操作需要动态执行。...
在本例中,我们将讨论如何使用 Oracle 存储过程编译,特别是使用 PL/SQL 语言编写的存储过程。 标题:Oracle 存储过程编译 描述:Oracle 存储过程编译 标签:Oracle 部分内容: 在上面的代码中,我们定义了一个...
下面是一个简单的示例,创建一个存储过程,动态执行 DML 语句,插入数据到上例中建好的 dinya_test 表中。 create or replace procedure proc_insert(id in number, name in varchar2) as str_sql varchar2(500...
通过在过程中使用输入参数,可以讲数据输入到执行部分,通过使用输出参数,可以将执行部分的数据输出到应用环境,在pl/sql中可以使用create procedure命令来创建过程。 编写一个存储过程,可以输入雇员名和新工资来...
Oracle 允许将PL/ SQL 语言编写的存储过程作为数据库对象存储在数据库中,存储过程通过语法分析,将第一 次执行编译的SQL 语句存储在高速缓冲存储器中,下次使用只需从高速缓冲区中调用已编译的代码,加速了SQL 语句的执...
7.5.7 SQL语句在PL/SQL中的运用 114 7.6 选择结构 114 7.6.1 格式1: IF_THEN_ELSE语句 114 7.6.2 格式2: IF_THEN_ELSE_IF语句 114 7.7 循环结构 114 7.8 异常处理(了解) 114 7.8.1 异常 114 7.8.2 PL/SQL是如何处理...
PL/SQL 是一种 procedural 语言,用于 Oracle 数据库中的存储过程和函数的编写。PL/SQL 使用包括变量声明、条件语句、循环语句、游标操作、异常处理等。 单元测试 单元测试是软件测试的一种,旨在验证软件中的最小...
实验四 PL/SQL存储过程 (2学时) 【实验目的】 (1)了解存储过程的使用方法。 (2)掌握存储过程的使用方法。 【实验要求】 (1)按照业务要求创建实现特定功能的存储过程。 (2)按照业务内容创建实现具有特定功能的函数...
调用RAISE_APPLICATION_ERROR存储过程 当数据库或PL/SQL在运行时发生错误时,一个异常被PL/SQL运行时引擎自动抛出。异常也可以通过RAISE语句抛出 RAISE exception_name; 显式抛出异常是程序员处理声明的异常的习惯...
在ORACLE系统里,触发器类似过程和函数,都有声明,执行和异常处理过程的PL/SQL块,不过有一点不同的是,触发器是隐式调用的,并不能接收参数。 触发器优点 (1)触发器能够实施的检查和操作比主键和外键约束、...
Application,development,sql*plus,worksheet,,4)pl/sql,developer,属于第三方软件,主要用于开发,测试,优化oracle,pl/sql,的 存储过程.如:触发器,此软件oracle不带,需要单独安装。,5)oracle的企业管理器(oem,...
10.2.5 将子查询因子化应用到PL/SQL中 270 10.3 递归子查询 273 10.3.1 一个CONNECT BY的例子 274 10.3.2 使用RSF的例子 275 10.3.3 RSF的限制条件 276 10.3.4 与CONNECT BY的不同点 276 10.4 复制CONNECT BY...
(名称:值加密) 使用 Oracle PL/SQL 轻松存储和检索名称:值对加密 (NVE) 数据的实用程序。 该项目的目标是能够使用最强大的加密方法轻松保存敏感信息。 该项目使用 Oracle 的 dbms_crypto 包使用 256 位 AES ...
* 熟悉游标、存储过程、存储函数、包以及触发器的应用 本篇资源摘要信息对数据库开发技术工具进行了详细的介绍,涵盖了Oracle数据库的发展历程、主要特点、版本等知识点,为学习数据库开发技术提供了良好的基础。