Если у вас есть проблемы с производительностью при циклическом просмотре каждой записи, но таблица слишком велика для одного обновления, вы можете рассмотреть возможность пакетного обновления с помощью BULK INTO ... LIMIT и FORALL.
CREATE TABLE klm (abc INTEGER, xyz INTEGER);
CREATE TABLE update_data (abc INTEGER, cdf INTEGER);
-- Have pairs of numbers (1000 rows)
INSERT INTO klm SELECT rownum, rownum FROM dual CONNECT BY level <= 1000;
-- Update every second row with 9999
INSERT INTO update_data SELECT rownum * 2, 9999 FROM dual CONNECT BY level <= 500;
DECLARE
CURSOR c1
IS
-- Select the key to be updated and the new value
SELECT abc, cdf FROM update_data;
-- Table type and table variable to store rows fetched from the cursor
TYPE t_update IS TABLE OF c1%rowtype;
update_tab t_update;
BEGIN
OPEN c1;
LOOP
-- Fetch next 30 rows into update table
FETCH c1 BULK COLLECT INTO update_tab LIMIT 30;
-- Exit when there were no more rows fetched
EXIT WHEN update_tab.count = 0;
-- This is the key point; uses update_tab to bulk-bind UPDATE statement
-- and run it for 30 rows in a single context switch
FORALL i IN 1..update_tab.count
UPDATE klm
SET klm.xyz = update_tab(i).cdf
WHERE update_tab(i).abc = klm.abc;
COMMIT;
END LOOP;
CLOSE c1;
END;
/
Объяснение этому заключается в том, что Oracle фактически имеет отдельные механизмы, выполняющие операторы SQL и программы PL/SQL. Всякий раз, когда процедура сталкивается с оператором SQL, она передает его механизму SQL для выполнения. Это называется «переключением контекста» и занимает много времени, особенно если выполняется в цикле.
Массовое связывание направлено на снижение этих накладных расходов за счет переключения контекста только один раз для каждой записи [массового размера]. Опять же, это, конечно, не так эффективно, как отдельная операция DML, но для больших таблиц или сложных запросов это может быть наилучшим возможным решением.
Я использовал описанный выше метод для обновления таблиц с записями 100–500 М с размером пакета 10–100 КБ, и он работал нормально. Но вам нужно поэкспериментировать с размером пакета в вашей среде для достижения наилучшей производительности.
person
Kombajn zbożowy
schedule
05.11.2013