1

由于我开始了将 7M 行从一个表插入另外两个表的过程,我现在想知道是否有更快的方法来执行此操作。该过程预计将在一个小时内完成,即 24 小时的处理时间。

事情是这样的:

此表中的数据

RAW (word VARCHAR2(4000), doc VARCHAR2(4000), count NUMBER);

应该在另外两个集群表 T1 和 T2 中找到新家

CREATE CLUSTER C1 (word VARCHAR2(4000)) SIZE 200 HASHKEYS 10000000;
CREATE CLUSTER C2 (doc VARCHAR2(4000)) SIZE 200 HASHKEYS 10000000;

T1 (word VARCHAR2(4000), doc VARCHAR2(4000), count NUMBER) CLUSTER C1(word);
T2 (doc VARCHAR2(4000), word VARCHAR2(4000), count NUMBER) CLUSTER C2(doc);

通过像这样手动提交的Java插入

stmtT1 = conn.prepareStatement("insert into T1 values(?,?,?)");
stmtT2 = conn.prepareStatement("insert into T2 values(?,?,?)");

rs = stmt.executeQuery("select word, doc, count from RAW");

conn.setAutoCommit(false);

while (rs.next()) {
    word = rs.getString(1);
    doc = rs.getString(2);
    count = rs.getInt(3);

    if (commitCount++==10000) { conn.commit(); commitCount=0; }

    stmtT1.setString(1, word);
    stmtT1.setString(2, doc);
    stmtT1.setInt(3, count);

    stmtT2.setString(1, doc);
    stmtT2.setString(2, word);
    stmtT2.setInt(3,count);

    stmtT1.execute();
    stmtT2.execute();
}

conn.commit();

有任何想法吗?

4

4 回答 4

3

我推荐的第一件事是做一个简单的插入-选择语句,让数据库处理所有的数据移动。如果您在两台机器之间移动数据,或者如果您没有足够大的回滚段来处理整个查询,那么它就不那么有用了。

我的第二件事是了解addBatch()方法。当您编写代码时,它会为您插入的每一行往返于数据库,这会增加网络开销。

第三,除非您在目标表中已经有很多行,否则在插入之前删除任何索引,然后重新创建。如果您保留索引,则必须为每一行更新它们,从而增加脏块开销。

最后:您需要聚簇表吗?我的经验是他们不会给你买很多东西(警告:这种体验是在单个表空间上的)。

于 2008-12-13T13:46:22.240 回答
1

好吧,您不能在 Oracle 中调用表 RAW ——它是一个保留字,因此会引发 ORA-00903 错误。

除此之外,您将使用:

insert all
into t1
into t2
select * from RAW
/

“逐行等于慢慢来” :)

于 2008-12-15T14:07:14.987 回答
0

除非您有特殊原因要在应用程序中处理数据,否则我会选择直接 INSERT AS SELECT。使用 Parallel DML 可以给您带来巨大的不同。

如果符合您的需要,还要检查 INSERT ALL 语法(1 次读取 2 次写入)。

除非你有 IO 问题,否则 1h 应该绰绰有余...

问候

于 2008-12-13T23:02:51.800 回答
0

在概念上类似于 addBatch,您可以编写一个 PL/SQL 过程,它接受(word、doc、count)的数组并在服务器端处理插入。它在概念上是相似的,因为您通过一次发送多个记录来减少网络旅行,并且您可以获得更快的性能。另一方面,它更加复杂和脆弱,因为它需要在服务器端编写 PL/SQL,并且在客户端需要额外的数组逻辑。Oracle TechNet 有几个这样的例子。

//尼古拉斯

于 2009-01-05T17:47:06.463 回答