很多人知道,在进行数据处理时,如果不产生日志或只产生少量的日志,将会有明显的、甚至是巨大的效率提升。下面有几条不同的SQL:

INSERT INTO T1 NOLOGGING;  
INSERT INTO T1 SELECT * FROM T2 NOLOGGING;  
INSERT /*+ NOLOGGING */ INTO T1 VALUES ('0');  
INSERT /*+ NOLOGGING */ INTO T1 SELECT * FROM T2;  
DELETE /*+ NOLOGGING */ FROM T1;  
UPDATE /*+ NOLOGGING */ T1 SET A='1';  

实际上,上述所有的SQL没有一个能够实现“不产生”日志的数据更改操作。第1-2条SQL语句虽然没有将NOLOGGING写为Hint的形式,但是也是很多人的错误写法,一并列在此处。事实上,NOLOGGING并不是Oracle的一个有效的Hint,而是一个SQL关键字,通常用于DDL语句中。这里NOLOGGING相当于给SELECT的表指定了一个别名为“NOLOGGING”。下面是NOLOGGING的一些正确用法:

CREATE TABLE T1 NOLOGGING AS SELECT * FROM T2;  
CREATE INDEX T1_IDX ON T1(A) NOLOGGING;  
ALTER INDEX T1_IDX REDUILD ONLINE NOLOGGING;  
ALTER TABLE T1 NOLOGGING;  

上述SQL中,最后一条SQL只是将表的LOGGING属性改为"NO"。而之前的几条SQL能够有效地减少DDL操作时减少的日志量。

在DML操作中,只有下面一种方式能够在大数据量时仍然只会产生极少量的日志:

INSERT /*+ APPEND */ INTO T1 SELECT * FROM T2;  

也就是使用append hint。但是这个hint要达到目的,需要以下几个条件:

使用INSERT /+ APPEND / INTO .. SELECT .. FROM形式的INSERT SQL。
如果是在归档模式下,需要将表的LOGGING属性置为NO。
表空间或数据库的FORCE LOGGING属性为NO。注意在非归档模式下也是可以设置FORCE LOGGING的。
这里提到的insert语句中的append hint,对于索引,仍然会产生日志,也就是说append hint对索引是没有效果的。
另外,DDL中使用的nologging关键字和inset语句中使用的append hint,并不是说完全不产生日志,只是对表的数据块的数据部分的更改不会有日志产生,但是SQL执行过程中数据字典的更改、空间分配等递归SQL、段头和位图块的更改、将数据块标记为unrecoverable等仍然会产生少量日志。

Related Posts