Будет ли вставлено полмиллиона записей с одинаковым значением даты из-за неуникального индекса в этом столбце даты? - PullRequest
3 голосов
/ 09 сентября 2010

У меня есть курсор, который выбирает все строки в таблице, чуть более 500 000 строк. Чтение строки из курсора, INSERT в другую таблицу, которая имеет два индекса, ни один из которых уникален, один числовой, один тип DATE COMMIT. Читайте следующую строку из Курсора, ВСТАВЛЯЙТЕ ... пока Курсор не опустеет.

Все значения моего столбца DATE совпадают с отметкой времени, инициализированной в начале сценария.

Эта штука работает 24 часа, только 464 тыс. Строк, чуть меньше 10 тыс. Строк / час.

Oracle 11g, 10 процессоров (!?) Что-то должно быть не так. Я думаю, что индекс DATE пытается обработать все эти записи с одинаковым значением для этого столбца.

Ответы [ 6 ]

3 голосов
/ 09 сентября 2010

Почему бы вам просто не сделать:

insert into target (columns....) 
select columns and computed values 
from source

commit

?

Это замедление наносит гораздо больший урон производительности, чем индекс, который не имеет никакого смысла.*

2 голосов
/ 09 сентября 2010

Индексы замедляют вставки, но ускоряют запросы.Это нормально.

Если возникла проблема, вы можете удалить индекс, вставить строки, а затем снова добавить индекс.Это может быть быстрее, если вы выполняете много операций вставки одновременно.

Способ, которым вы копируете данные с помощью курсоров, кажется неэффективным.Вместо этого вы можете попробовать подход, основанный на множестве:

INSERT INTO table1 (x, y, z)
SELECT x, y, z FROM table2 WHERE ...
1 голос
/ 09 сентября 2010

Фиксация после каждой вставленной строки не имеет особого смысла. Например, если вас беспокоит превышение емкости отмены, вы можете сохранить количество вставок и выполнить коммит после каждой тысячи строк.

Обновление индексов будет иметь некоторое влияние, но это неизбежно, если вы не можете удалить (или отключить), пока вставки выполняются, но это только так. Я ожидаю, что коммиты окажут большее влияние, хотя я подозреваю, что это тема с различными мнениями.

Предполагается, что у вас есть веская причина для вставки из курсора, а не в качестве прямой insert into ... select from модели.

0 голосов
/ 09 сентября 2010

Договорились о том, что ваше время убивает медленная обработка. Копирование 500 000 строк должно занимать считанные минуты.

Один подход INSERT ... SELECT FROM .... был бы лучшим, если у вас достаточно большие сегменты отката. База данных может даже автоматически применять параллельные методы к простому оператору SQL, который не будет применяться с PL / SQL.

Кроме того, вы можете взглянуть на подсказку / * + APPEND * / - прочитать ее и посмотреть, может ли это быть применимо к ситуации с вашей целевой таблицей.

o чтобы использовать все 10 ядер, вам понадобится либо использовать простой параллельный SQL, либо запустить 10 копий вашего блока pl / sql, разделив исходную таблицу на 10 копий.

В Oracle 10 это ручная задача (накатить собственный параллелизм), но Oracle 11.2 представляет DBMS_PARALLEL_EXECUTE.

Если это не удастся, следующим шагом будет увеличение объема выборки / вставки с использованием BULK COLLECT и групповой вставки - процесс в кусках по 1000 или более строк (или больше). Опять же посмотрите, может ли DBMS_PARALLEL_EXECUTE помочь вам, или вы могли бы отправить работу по частям через DBMS_JOB.

(Предостережение: у меня нет доступа ни к чему более позднему, чем Oracle 10)

0 голосов
/ 09 сентября 2010

Для таких операций вы должны смотреть на массовые операции Oracle, используя FORALL и BULK COLLECTЭто значительно сократит количество операций DDL над базовыми таблицами

create or replace procedure fast_proc is
    type MyTable is table of source_table%ROWTYPE;
    MyTable table;
    begin
        select * BULK COLLECT INTO table from source_table;

         forall x in table.First..table.Last
             insert into dest_table values table(x) ;
    end;
0 голосов
/ 09 сентября 2010

Как правило, хорошей идеей является удаление индексов перед выполнением массовой вставки, а затем добавление их впоследствии, чтобы БД не пытался обновлять индексы при каждой вставке. Прошло много времени с тех пор, как я использовал oracle, но пытались ли вы вставить в транзакцию более одного оператора вставки? Это также должно ускорить его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...