Oracle 11g - 如何优化慢速并行插入选择?

时间:2013-11-18 12:17:31

标签: sql performance oracle parallel-processing oracle11g

我们希望加快下面的并行插入语句的运行。我们期望插入大约80M的记录,大约需要2个小时才能完成。

INSERT /*+ PARALLEL(STAGING_EX,16) APPEND NOLOGGING */ INTO STAGING_EX (ID, TRAN_DT, 
RECON_DT_START, RECON_DT_END, RECON_CONFIG_ID, RECON_PM_ID) 
SELECT /*+PARALLEL(PM,16) */ SEQ_RESULT_ID.nextval, sysdate, sysdate, sysdate, 
'8a038312403e859201405245eed00c42', T1.ID FROM PM T1 WHERE STATUS = 1 and not 
exists(select 1 from RESULT where T1.ID = RECON_PM_ID and CREATE_DT >= sysdate - 60) and 
UPLOAD_DT >= sysdate - 1 and (FUND_SRC_TYPE = :1) 

我们认为缓存not exists列的结果会加快插入速度。我们如何执行缓存?有什么想法加快插入速度?

请参阅以下有关企业管理器的计划统计信息。我们还注意到这些语句并不是并行运行的。这是正常的吗?

insert-select plan statistics from oracle em

编辑:顺便说一下,序列已缓存到1M

3 个答案:

答案 0 :(得分:5)

改进统计信息。估计的行数为1,但实际行数超过700万并且正在计数。这会导致执行计划使用嵌套循环而不是散列连接。嵌套循环可以更好地处理少量数据,并且散列连接可以更好地处理大量数据。修复可能就像确保相关表格具有准确的当前统计数据一样简单。这通常可以通过使用默认设置收集统计信息来完成,例如:exec dbms_stats.gather_table_stats('SIRS_UATC1', 'TBL_RECON_PM');

如果这不能改善基数估算,请尝试使用动态采样提示,例如/*+ dynamic_sampling(5) */。对于这样一个长期运行的查询,如果能够获得更好的计划,则需要花费额外的时间预先采样数据。

使用语句级并行而不是对象级并行。这可能是并行SQL最常见的错误。如果使用对象级并行,则提示必须引用对象的别名。从11gR2开始,无需担心指定对象。此语句只需要一个提示:INSERT /*+ PARALLEL(16) APPEND */ ...。请注意,NOLOGGING不是真正的提示。

答案 1 :(得分:3)

尝试使用更多绑定变量,尤其是在可能发生嵌套循环的情况下。我注意到你可以在

这样的情况下使用它
CREATE_DT >= :YOUR_DATE instead of CREATE_DT >= sysdate - 60 

我认为这可以解释为什么在执行计划的最低部分执行了1.8亿次,即使更新查询的其他部分仍然是7900万中的800万。

答案 2 :(得分:0)

我可以看到两大问题:

1 - 提示并行(在选择中)NO NOT work,因为它应该像这样+ PARALLEL(T1,16)

2 - SELECT不是最优的,如果避免表达式NOT IN

会更好