Oracle:在索引表上插入,避免重复。寻找提示和建议

时间:2010-03-29 18:02:30

标签: performance oracle plsql

我正在寻找最佳解决方案(性能明智)来实现这一目标。

我必须在表格中插入记录,避免重复。

例如,取表A

Insert into A (
 Select DISTINCT [FIELDS] from B,C,D.. 
 WHERE (JOIN CONDITIONS ON B,C,D..)
 AND 
 NOT EXISTS
 ( 
   SELECT * FROM A ATMP WHERE
   ATMP.SOMEKEY = A.SOMEKEY
 )
);

我有A.SOMEKEY的索引,只是为了优化NOT EXISTS查询,但我意识到在索引表上插入会受到性能影响。

所以我想在全局临时表中复制表A,在那里我会保留索引。然后,从表A中删除索引并执行查询,但修改了

Insert into A (
 Select DISTINCT [FIELDS] from B,C,D.. 
 WHERE (JOIN CONDITIONS ON B,C,D..)
 AND 
 NOT EXISTS
 ( 
   SELECT * FROM GLOBAL_TEMPORARY_TABLE_A ATMP WHERE
   ATMP.SOMEKEY = A.SOMEKEY
 )
);

这将解决“在索引表上插入”,但我必须在每次插入时更新全局临时A。

我有点迷失在这里,

有没有更好的方法来实现这一目标?

提前致谢,

2 个答案:

答案 0 :(得分:2)

如果列A.SOMEKEY被声明为NOT NULL并且如果插入大量数据,则NOT IN子句可能比NOT EXISTS更有效,因为它可以使用HASH ANTI-JOIN。

INSERT INTO A
   (SELECT DISTINCT FIELDS
      FROM B, C, D ..
     WHERE (JOIN CONDITIONS ON B, C, D..)
       AND [B].SOMEKEY NOT IN (SELECT SOMEKEY FROM A)
       AND [B].SOMEKEY IS NOT NULL;

HASH ANTI-JOINS对于大型数据集非常有效。

在这种情况下,我认为临时表不是一个好主意,因为您将处于以下两种情况之一:

  1. 临时表是在SOMEKEY上编入索引的,你关于插入索引表的观点因此是没有意义的
  2. 临时表未编入索引且您的反连接效率低下
  3. 哪种方法效率最高可能取决于数据量。

答案 1 :(得分:0)

如何在表A上设置索引。 使用NOLOGGING

创建表b(与表a相同的结构)
Insert /*+APPEND */ into b (
 Select DISTINCT [FIELDS] from B,C,D.. 
 WHERE (JOIN CONDITIONS ON B,C,D..)
 AND 
 NOT EXISTS
 ( 
   SELECT * FROM A ATMP WHERE
   ATMP.SOMEKEY = A.SOMEKEY
 )
);

然后将索引放在A和INSERT INTO A SELECT * FROM B

你可以使B成为一个全局临时表,但要确保数据对于会话是持久的,因为丢弃索引将意味地提交。