攻略1-7 数据加载速度最大化

问题描述

你要将大量数据加载到一张表中,并需要尽可能快地插入新数据。

解决方案

首先,将表的日志属性设置为NOLOGGING。这将会为直接路径运算生成最少的重做日志(这个特性对于正常的DML运算不会有影响)。然后像下面这样来使用直接路径加载功能:

 在使用子查询来确定要插入哪些记录时,在查询中加入INSERT /*+ APPEND /; 
 在使用VALUES子句的查询中加入INSERT /
+ APPEND_VALUES */; 
 使用CREATE TABLE...AS SELECT语句。 
下面是用来说明NOLOGGING和直接路径加载的例子。首先,运行下面的查询来验证表的日志记录状态。

enter image description here

上面这个语句是加载数据的一种高效方法,因为INSERT /*+APPEND */等直接路径操作与NOLOGGING结合起来,将会产生数量最少的重做。

同时,还要确保提交了通过直接路径加载的数据,否则将不能看到这些数据。因为Oracle会报ORA-12838的错误,表明直接路径加载的数据在能够查询之前必须先提交。

注意 当使用直接路径向表中插入数据的时候,Oracle将会把新的数据行插入到高水位线之上。即使在执行DELETE语句之后有大量的可用空间,Oracle也会将这些新插入的数据存到高水位线之上。这可能会导致表占用大量的磁盘空间,但实际上并没有那么多数据。

工作原理

直接路径插入比通常的插入语句在性能上具有两个优势。

 如果指定了NOLOGGING,则会生成最少量的重做。 
 避开了缓冲区缓存,直接将数据加载到数据文件中。这样能够极大地提升加载性能。 
NOLOGGING特性只能够使直接路径操作所产生的重做最小化。对于直接路径插入,NOLOGGING选项能够显著提高加载速度。有一种观点认为NOLOGGING能够减少所有DML操作为表所生成的重做的数量,这是不正确的。NOLOGGING特性并不会影响正常的INSERT、UPDATE、MERGE以及DELETE等语句的重做生成。

减少重做生成的一个负面影响就是,如果在数据加载后(对表进行备份之前)出现了错误,那么不能通过NOLOGGING恢复创建的数据。如果你愿意冒丢失数据的风险,那么可以使用NOLOGGING,并在表中数据加载之后马上对表进行备份。如果是关键数据,那么不要使用NOLOGGING。如果数据能够很容易地重建,那么在你想要提升大数据量加载的性能时,就可以考虑使用NOLOGGING。

如果在NOLOGGING模式下填充数据到一张表之后(并且在对表进行备份之前),发生了介质故障会怎么样呢?在进行恢复或修复操作之后,它看上去似乎又恢复原样了:

enter image description here

上面的输出表明,表中的数据是无法恢复的。只有在数据并不是关键数据,或者在创建数据后马上能对其进行备份的情况下,才能使用NOLOGGING。

提示 如果你使用RMAN对数据库进行备份,则可以使用REPORT UNRECOVERABLE命令来报告不可恢复的数据文件。

NOLOGGING有一些怪癖需要进一步解释一下。你可以在数据库、表空间以及对象级指定日志记录特性。如果数据库启用了强制日志记录,则会覆盖对表指定的NOLOGGING。如果在表空间级指定了日志记录子句,则也将会为任何没有显式使用日志记录子句的CREATE TABLE语句设置默认的日志记录值。

可以使用下面的语句来验证数据库的日志记录模式:

enter image description here

接下来的这条语句验证表空间的日志模式:

enter image description here

如何判断Oracle是否为某个操作记录了重做日志呢?一种途径就是比较这种操作在启用日志记录和NOLOGGING模式下所产生的重做量的大小。如果可以在开发环境中进行测试,则可以去监控在事务发生时,重做日志多长时间切换一次。另一个简单的测试就是比较一下在有和没有日志时,操作所花的时间。在NOLOGGING模式下进行的操作应该更快,因为在加载过程中仅产生了很少的重做信息。

目录