oracle 优化之批量处理bulk correct 和 forall

世风之狡诈多端,到底忠厚人颠扑不破; 末俗以繁华相尚,终觉冷淡处趣味弥长。

BULK   COLLECT运用

在游标中运用

declare

cursor C_CUR is SELECT * FROM  T_TEST;

TYPE T_TYPE IS TABLE OF  T_TEST%ROWTYPE;----需要定义一个数据记录的类型

C_REC  T_TYPE;

begin

open C_CUR ;

loop

FETCH  C_CUR BULK COLLECT INTO C_REC LIMIT 5000;

EXIT WHEN  C_REC.COUNT=0; ---这个地方不可以用   exit when C_CUR%notfound 会导致少记录  如果用的话可以在循环结束的时候用,这是区别于普通游标的一个关键地方

for I in C_REC.first..C_REC.LAST

LOOP

INSERT INTO MXQ(ID,NAME)  VALUES (C_REC(I).ID,C_REC(I).NAME);

UPDATE  MXQ  SET ID=C_REC(I).ID WHERE  NAME=C_REC(I).NAME;

END LOOP;

EXIT  WHEN C_CUR%NOTFOUND;--粉色标明的地方 可以任意选择一个退出循环

end loop;

close C_CUR;

end;

forall 运用

forall也是一个集合提取 它不同于for循环的地方在于

1.它不是一个循环 不用接loop 和 end loop

2.forall 后面只能跟一个dml语句.否则会报错.

综合运用BULK CORRECT 和 forall之后以上sql核心部分可以改写成这样

loop

FETCH  C_CUR BULK COLLECT INTO C_REC LIMIT 5000;

EXIT WHEN  C_REC.COUNT=0;

forall I in C_REC.first..C_REC.LAST

INSERT INTO MXQ(ID,NAME)  VALUES (C_REC(I).ID,C_REC(I).NAME);----forall 后面只能跟一个dml语句

forall I in C_REC.first..C_REC.LAST

UPDATE  MXQ  SET ID=C_REC(I).ID WHERE  NAME=C_REC(I).NAME;

end loop;

关于fetch bulk collect into 游标记录类型的声明

声明一个表中的记录

DECLARE

CURSOR C_CUR IS SELECT * FROM TAB_TEST;

TYPE C_TYPE IS TABLE OF TAB_TEST%ROWTYPE;

C_REC C_TYPE;

声明多个表中的记录

DECLARE

CURSOR C_CUR IS SELECT A.ROWID,B.NAME FROM TAB_TEST_1 A,TAB_TEST_2 B WHERE A.ID=B.ID;

TYPE  C_TYPE_REC IS RECORD (ROWID    VARCHAR2(32),

NAME      TAB_TEST_2%TYPE );----因为是两个表中的字段所以需要声明一个记录类型record包含这两个表的字段

TYPE  C_TYPE IS TABLE OF C_TYPE_REC;----把类型声明成刚才那个记录的类型,  注意不需要%ROWTYPE   因为C_TYPE_REC已经是一个记录类型了

C_REC C_TYPE;

测试 效率  数据270万 环境11g

用BULK COLLECT  和  forall

写法一

DECLARE

CURSOR C_CUR IS SELECT A.ROWID FROM mxq A;
TYPE C_TYPE IS TABLE OF C_CUR%ROWTYPE;
C_REC C_TYPE;
BEGIN
OPEN C_CUR;
LOOP
FETCH C_CUR BULK COLLECT INTO C_REC LIMIT 10000;
EXIT WHEN C_REC.count=0;
FORALL I IN C_REC.FIRST..C_REC.LAST
UPDATE mxq A SET A.BEIZHU=(SELECT BEIZHU FROM mxq_1 B WHERE A.SNAME=B.SNAME ) WHERE A.ROWID=C_REC(I).ROWID;
commit;
END LOOP;
CLOSE C_CUR;
END; 222秒

写法二

DECLARE
CURSOR C_CUR IS SELECT A.ROWID,B.BEIZHU FROM mxq A,mxq_1 B WHERE A.SNAME=B.SNAME;
TYPE C_TYPE IS TABLE OF C_CUR%ROWTYPE;
C_REC C_TYPE;
BEGIN
OPEN C_CUR;
LOOP
FETCH C_CUR BULK COLLECT INTO C_REC LIMIT 10000;
EXIT WHEN C_REC.count=0;
FORALL I IN C_REC.FIRST..C_REC.LAST
UPDATE mxq A SET A.BEIZHU=C_REC(I).BEIZHU WHERE A.ROWID=C_REC(I).ROWID;
commit;
END LOOP;
CLOSE C_CUR;
END; 267秒

这两个写法加载进游标的数据记录不一样经过测试发现 差距不大.

用两种写法分别使用批处理和不使用批处理

不用BULK COLLECT  和  forall

写法一

DECLARE 

CURSOR C_CUR IS SELECT A.ROWID FROM mxq A;
C_REC C_CUR%ROWTYPE;
BEGIN
OPEN C_CUR;
LOOP
FETCH C_CUR INTO C_REC ;
EXIT WHEN C_CUR%NOTFOUND;
UPDATE mxq A SET A.BEIZHU=(SELECT BEIZHU FROM mxq_1 B WHERE A.SNAME=B.SNAME ) WHERE A.ROWID=C_REC.ROWID;
commit;
END LOOP;
CLOSE C_CUR;
END;1000秒

写法二

DECLARE
CURSOR C_CUR IS SELECT A.ROWID,B.BEIZHU FROM mxq A,mxq_1 B WHERE A.SNAME=B.SNAME;
C_REC C_CUR%ROWTYPE;
BEGIN
OPEN C_CUR;
LOOP
FETCH C_CUR INTO C_REC ;
EXIT WHEN C_CUR%NOTFOUND;
UPDATE mxq A SET A.BEIZHU=C_REC.BEIZHU WHERE A.ROWID=C_REC.ROWID;
commit;
END LOOP;
CLOSE C_CUR;
END;804秒

不用批处理的dml语句 写法二比写法一快的明显一些快了200秒.

总结

1.批处理比单条处理快了大概4倍.

2.sql写法也一定程度上决定了dml的速度.

3可以用并发来提高dml速度,可以看我之前对并发做的测试.

最后送看文章的小伙伴一句话

乾坤未定,你我皆是黑马.

原文地址:https://www.cnblogs.com/throughRiversandLake/p/10894482.html

时间: 2024-11-09 05:50:36

oracle 优化之批量处理bulk correct 和 forall的相关文章

Oracle 优化和性能调整

分析评价Oracle数据库性能主要有数据库吞吐量.数据库用户响应时间两项指标.数据库用户响应时间又可以分为系统服务时间和用户等待时间两项,即:  数据库用户响应时间=系统服务时间+用户等待时间  因此,获得满意的用户响应时间有两个途径:一是减少系统服务时间,即提高数据库的吞吐量:二是减少用户等待时间,即减少用户访问同一数据库资源的冲突率.  数据库性能优化包括如下几个部分:  调整数据结构的设计 这一部分在开发信息系统之前完成,程序员需要考虑是否使用Oracle数据库的分区功能,对于经常访问的数

oracle常用的复合数据类型 : BULK COLLECT(成批聚合类型)和数组集合type类型is table of 表%rowtype index by binary_integer

例1: 批量 查询部门号为 "10" 号的并把它们打印出来 . DECLARE TYPE emp_table_type IS TABLE OF my_emp%ROWTYPE INDEX BY BINARY_INTEGER; v_emp_table emp_table_type; BEGIN SELECT * BULK COLLECT INTO v_emp_table FROM my_emp WHERE deptno=&deptno; FOR i IN 1..v_emp_tabl

ORACLE优化器RBO与CBO介绍总结

RBO和CBO的基本概念 Oracle数据库中的优化器又叫查询优化器(Query Optimizer).它是SQL分析和执行的优化工具,它负责生成.制定SQL的执行计划.Oracle的优化器有两种,基于规则的优化器(RBO)与基于代价的优化器(CBO) RBO: Rule-Based Optimization 基于规则的优化器 CBO: Cost-Based Optimization 基于代价的优化器 RBO自ORACLE 6以来被采用,一直沿用至ORACLE 9i. ORACLE 10g开始,

oracle优化思考-双刃剑

oracle优化是一个双刃剑,特别注意这把剑用的场合:系统规划OLTP or OLAP 优化1:索引 在DML操作时,必须维护索引,如果大量的DML操作,想想看,IO是不是老高了? 索引优点:在很多时候能提高查询速度,减低IO负载 优化2: 主键使用序列,而序列的cache大小设置 如果cache设置的小,有可能造成DML锁 如果cache设置的大,DB异常关机后,已经发出的但是未提交的cache数会被丢弃,这样就造成主键的不连续 ----未完(持续更新) oracle优化思考-双刃剑,布布扣,

【Oracle 优化】Oracle数据库提高命中率及相关优化

本文是关于Oracle数据库调试与优化方面的文章,主要介绍Oracle数据库中命中率相关的问题,包括不同的算法之间性能的比对. 关于Oracle中各个命中率的计算以及相关的调优 1)Library Cache的命中率: .计算公式:Library Cache Hit Ratio = sum(pinhits) / sum(pins) SQL>SELECT SUM(pinhits)/sum(pins) FROM V$LIBRARYCACHE; 通常在98%以上,否则,需要要考虑加大共享池,绑定变量,

Oracle 关联并且批量修改

描述:A表有 id,or_id 字段,B表有 id,code 字段 A表有  or_id 与B表的  id 关联,现要将A.or_id 替换成  B.code 数据 UPDATE  ASET A.OR_ID=(SELECT  code                    FROM  B                   WHERE B.ID=A.OR_ID) Oracle 关联并且批量修改,布布扣,bubuko.com

Oracle优化器和执行计划

1. 优化器(Optimizer)是sql分析和执行的优化工具,它负责制定sql的执行计划,负责保证sql执行效率最高,比如决定oracle以什么方式访问数据,全表扫描(full table scan)还是索引范围(index range scan)扫描,还是全索引快速扫描(index fast full scan, INDEX_FFS),对于表关联查询,是用什么方式关联.有2种优化器,RBO和CBO,从oracle 10g开始,RBO已经被弃用,但是仍可以通过hint的方式使用. 2. RBO

oracle 优化or 替换为in、exists、union all的几种写法,测试没有问题!

oracle 优化or 替换为in.exists.union的几种写法,测试没有问题! 根据实际情况用选择相应的语句吧!如果有索引,or全表扫描,in 和not in 也要慎用,否则会导致全表扫描,  select *    from T_Pro_Product   where bar_code = 'nnnmmm'      or name = 'nnnmmm'      or no = 'nnnmmm'; select * from T_Pro_Product where 'nnnmmm'

oracle优化-leading提示和ordered提示以及materialize提示

以下内容适用于oracle 10.2.0.5及其以上版本 一个查询很慢,原始SQL如下: 1 select 2 a.* 3 from (select 4 ssi.ID, 5 'small_station_info' TB, 6 (select sbi.name 7 from scene_base_info sbi 8 where sbi.id = ssi.antenna_selection) as antenna_selection, 9 ssi.antenna_height, 10 ssi.d