oracle笔记整理13——性能调优之SQL优化

1) 3种游标循环性能

a) 单条处理

declare
        cursor 游标 is
begin
open 游标;
LOOP  
FETCH 游标 INTO 变量;
EXIT WHEN  条件;
END LOOP;
CLOSE 游标;
end;

逐条处理,效率之低,不敢想象。

b) 批量处理

declare
        cursor 游标 is
begin
open 游标;
FETCH 游标 BULK COLLECT INTO 变量;
EXIT WHEN  条件;
CLOSE 游标;
end;

一次FETCH出来.一次处理所有行,效率最高。

declare
  cursor c is
    select *
      from table1;
  type c_type is table of c%rowtype;
  v_type c_type;
begin
  open c;
  loop
    fetch c bulk collect
      into v_type limit 100000;
    exit when c%notfound;
    <<inner1>>
    begin
    forall i in 1 .. v_type.count
      insert /*+append*/
      into table2
      values v_type
        (i);
    commit;
    EXCEPTION    ----出错后忽略继续执行
      WHEN OTHERS THEN
        null;
    end inner1;
  end loop;
  close c;
  commit;
end;
--删除
delete from table2 where read_id = v_type(i);

c) 游标for循环

for c in (sql语句) loop
……
end loop;

效率非常接近于批量处理,这种隐式循环的游标语句,其实也是一种批量处理的过程,它每次读取了近100行数据到缓存.

d) 结论:在不使用集合变量(bulk collect into)的情况下,选择隐式游标,既简洁又高效。

http://www.2cto.com/database/201307/224636.html

2) 多用commit

在确保完整性的情况下多用commit提交,可以释放事务所占的资源,包括redo缓存、undo表空间、锁、管理这些资源的内部花费。
大表进行insert,update,delete时可以分批进行,小批量提交。

3) exists与in

a) 示例:select * from A where exists (select 1 from B where A.id = B.id)

b) 原理:通过使用EXISTS,Oracle会首先检查主查询,然后运行子查询直到它找到第一个匹配项;Oracle在执行IN时,首先执行子查询,并将获得的结果存放临时表中,再执行主查询。

c) 在选择了合理的驱动表情况下,基于CBO时,A、B两表数据量差别越大,exists的性能越好。在RBO/11g时代,exists与in在性能上是一样的,经过cost最低转换之后都采用了hash join的连接方式,影响性能的关键因素在于能否选择合适的驱动表。

d) 结论:在RBO/11g中还是尽量采用exists,RBO是基于统计信息的,一旦统计信息没有及时更新,就会出现性能问题。

4) not in和not exists

a) 在RBO/11g中,都采用hash join方式,子查询的数据量越大,not exists的效率越高,not exists子查询中可以使用索引,但是 not in的子查询中无法使用索引,在都不使用索引的情况下,not in与not exists无性能差别。

b) 空值null的影响:当外层表存在空值时,not in直接忽略此空值,not exists不会受影响,正常数据。当内层表为空时,not in导致返回的最终查询结果为空,not exists则不受影响。

c) 结论:不管是出于性能方面,还是防止null值干扰输出结果方面,建议尽量使用not exists

5) nologging

只有在如下情况下,nologging才会生效,普通的DML语句无效。

a)  direct load (SQL*Loader)(load文件、load命令形式) b) direct load INSERT (using APPEND hint)(模拟直接加载) c) create table XXX nologging as select * from ……;
d)  insert /*+ APPEND */ into xxx nologging ……; e) create index …… nologging;
f)  create table name as selectinsert into在nologging状态下性能相当,但是在正常情况下,create由于其为DDL操作,日志量很少,故性能最好,因此可能的情况下,尽量选择create。 g) 一般情况nologging、append、parallel同时使用会大幅提高性能。

6) 减少远程访问及次数

7) 先删索引,再插数据,最后重建索引(建并行索引,之后再alter parallel为1)。

你可能感兴趣的:(oracle,性能,Cursor,exists,nologging)