#sql #oracle
Есть задача загрузки csv файла через Web интерфейс. Во время загрузки на стороне клиента выполняются проверки на корректность данных в файле. Сейчас мы вставляем миллионы строк вызывая процедуру вставки одной строки. То есть, для каждой строки файла вызывается процедура. Схематичный вид процедуры: procedure example(iValue1 IN Table.column1, iValue2 IN Table.column2, iValue3 IN Table.column3) is begin insert into table(column1, column2, column3) values (iValue1, iValue3, iValue3); end; Вызов миллионов раз это процедуры работает непозволительно медленно. Как можно изменить подход для ускорения процесса вставки?
Ответы
Ответ 1
Если нет возможности воспользоваться SQL*loader или insert from External Table, то можно попробовать использовать bulk insert: DECLARE TYPE prod_tab IS TABLE OF products%ROWTYPE; products_tab prod_tab := prod_tab(); start_time number; end_time number; BEGIN -- Populate a collection - 100000 rows SELECT * BULK COLLECT INTO products_tab FROM products; EXECUTE IMMEDIATE 'TRUNCATE TABLE products'; Start_time := DBMS_UTILITY.get_time; FOR i in products_tab.first .. products_tab.last LOOP INSERT INTO products (product_id, product_name, effective_date) VALUES (products_tab(i).product_id, products_tab(i).product_name, products_tab(i).effective_date); END LOOP; end_time := DBMS_UTILITY.get_time; DBMS_OUTPUT.PUT_LINE(‘Conventional Insert: ’||to_char(end_time-start_time)); EXECUTE IMMEDIATE 'TRUNCATE TABLE products'; Start_time := DBMS_UTILITY.get_time; FORALL i in products_tab.first .. products_tab.last INSERT INTO products VALUES products_tab(i); end_time := DBMS_UTILITY.get_time; DBMS_OUTPUT.PUT_LINE(‘Bulk Insert: ’||to_char(end_time-start_time)); COMMIT; END; Примеры использования BULK COLLECT и FORALL...Ответ 2
Дело в том что при использовании процедуры у вас постоянно переключается контекст с PL/SQL на SQL, это затратная операция. Тут могут быть только два варианта оптимизации: Самый быстрый, если данные можно запросить из таблицы: insert into Table1 (column1, column2, column3) select iValue1, iValue2, iValue3 from Table2; Если без процедуры ни как, то проверьте, возможно commit делается после каждого вызова example, нужно вызывать его один раз после вставки всех строк.
Комментариев нет:
Отправить комментарий