Таблица Hash кластера Oracle с более быстрой вставкой

Так как я начал процесс вставки 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();

Любые идеи?

13.12.2008 12:41:38
4 ОТВЕТА

Первое, что я бы порекомендовал, это сделать простой оператор вставки-выбора и позволить базе данных обрабатывать все перемещения данных. Не очень полезно, если вы перемещаете данные между двумя компьютерами или если у вас нет сегментов отката, достаточно больших для обработки всего запроса.

Второе, что я должен узнать о методе addBatch () . Когда вы написали свой код, он выполняет обход в базу данных для каждой вставляемой строки, что увеличивает нагрузку на сеть.

В-третьих, если у вас уже нет большого количества строк в таблицах назначения, нужно удалить любые индексы перед вашими вставками и воссоздать после. Если вы оставите индексы на месте, они должны будут обновляться для каждой строки, добавляя к ненужному заголовку грязного блока.

И наконец: вам нужны кластерные таблицы? Мой опыт показывает, что они не покупают вас много (предостережение: этот опыт был на одном табличном пространстве).

3
13.12.2008 13:46:22
эй, спасибо за твой совет. Я использую Java для мониторинга процесса передачи данных (сколько осталось строк), обычный INSERT AS SELECT не говорит мне. Я всегда обращаюсь к таблицам одним и тем же способом, например select * from T1, где word = 'foo'; для этого хеш-таблицы являются лучшими, я думаю.
chris 15.12.2008 02:36:39
Основываясь на прошлом опыте работы с базами данных с хэш-индексированием (Teradata), я бы обратился к хеш-кластерам, только если вы объединяете несколько таблиц с одним и тем же ключом - и, как я заметил, я не увидел особой пользы, когда попробовал это. Для вашего запроса лучше всего использовать нормальный индекс B-дерева.
kdgregory 15.12.2008 16:01:33
Если вы используете INSERT INTO .. ​​SELECT FROM синтаксис, вы можете использовать v $ longops, чтобы увидеть, где он.
WW. 13.08.2009 14:59:36
+1 за исключением того, что хеш-кластеризация, используемая правильно, является реальным спасением. Одно логическое чтение, чтобы найти все записи из нескольких таблиц, может быть на порядок лучше, чем альтернативы.
David Aldridge 13.08.2009 21:46:58

Если у вас нет особых причин для обработки данных в приложении, я бы пошел на прямую INSERT AS SELECT. Использование Parallel DML может дать вам огромную разницу.

Проверьте также INSERT ALL синтаксис (1 чтение для 2 записей), если это соответствует вашим потребностям.

Если у вас нет проблем с вводом-выводом, 1ч должно быть более чем достаточно ...

С уважением

0
13.12.2008 23:02:51

Ну, вы не можете назвать таблицу RAW в Oracle - это зарезервированное слово, поэтому будет возникать ошибка ORA-00903.

Помимо этого, вы бы использовали:

insert all
into t1
into t2
select * from RAW
/

«Ряд за строкой - медленно, медленно» :)

1
15.12.2008 14:07:14

Концептуально аналогично addBatch, вы могли бы написать процедуру PL / SQL, которая принимает массивы (word, doc, count) и обрабатывает вставки на стороне сервера. Концептуально это похоже, поскольку вы сокращаете количество сетевых поездок, отправляя несколько записей за один раз, и вы можете добиться более высокой производительности. С другой стороны, он более сложный и хрупкий, поскольку требует написания PL / SQL на стороне сервера и потребует дополнительной логики массива на стороне клиента. Oracle TechNet имеет несколько примеров этого.

// Николай

0
5.01.2009 17:47:06