2013-08-30 11 views
1

У меня есть таблицы и каждый из них имеет не менее 35M данных. Я закодировал сценарий массового обновления, как показано ниже: . Я хотел бы знать, что мне нужно, чтобы настроить параметр Limit=10000, чтобы запустить этот скрипт с лучшей производительностью.Настроить предельный параметр PLSQL при массовом обновлении

DECLARE 
    CURSOR rec_cur IS 
    SELECT id,sirname 
    FROM table_user; 

    TYPE num_tab_t IS TABLE OF NUMBER; 
    TYPE vc2_tab_t IS TABLE OF VARCHAR2(15); 

    id_tab NUM_TAB_T; 
    sirname_tab VC2_TAB_T; 
BEGIN 
    OPEN rec_cur; 
    LOOP 
     FETCH rec_cur BULK COLLECT INTO id_tab, sirname_tab LIMIT 10000; 
     EXIT WHEN id_tab.COUNT() = 0; 
     FORALL i IN id_tab.FIRST .. id_tab.LAST   
      UPDATE table_user_backup 
      SET sirname = sirname_tab(i) 
      ,  sirname_date = sysdate 
      WHERE id = id_tab(i); 
    END LOOP; 
    CLOSE rec_cur; 
END; 

Я проверил три возможных способа массового обновления, поделившись каждым из них прошедшим временем. Он показывает, что SQL лучше, чем pl-sql для полного массового обновления. После изменения параметра Limit в диапазоне 1000-100000, я не мог видеть, какая-то разница

-- Bulk update --for 2.5M entries 


--Takes 4 Minutes 
DECLARE 
    CURSOR rec_cur IS 
     SELECT id,name 
     FROM table_user; 
    BEGIN 

     FOR sub in rec_cur 
     LOOP 
      UPDATE table_user_backup 
       SET name_date = sysdate 
       WHERE id = sub.id; 
     END LOOP; 

END; 


--takes 2.5 minutes 
DECLARE 
    CURSOR rec_cur IS 
    SELECT id,name 
    FROM table_user; 

    TYPE num_tab_t IS TABLE OF NUMBER; 
    TYPE vc2_tab_t IS TABLE OF VARCHAR2(20); 

    id_tab NUM_TAB_T; 
    name_tab VC2_TAB_T; 
BEGIN 
    OPEN rec_cur; 
    LOOP 
     FETCH rec_cur BULK COLLECT INTO id_tab, name_tab LIMIT 10000; 
     EXIT WHEN id_tab.COUNT() = 0; 

     FORALL i IN id_tab.FIRST .. id_tab.LAST   
      UPDATE table_user_backup 
      SET name = name_tab(i) 
      ,  name_date = sysdate 
      WHERE id = id_tab(i); 
    END LOOP; 
    CLOSE rec_cur; 
END; 

--SQL is faster than pl sql 
--takes 2.0 minutes 
UPDATE table_user_backup tu_backup 
    SET (name, name_date) = (SELECT name, sysdate 
            FROM table_user tu 
            WHERE tu_backup.id = tu.id) 
WHERE EXISTS(SELECT 1 
       FROM table_user tu 
       WHERE tu.id=tu_backup.id); 

ответ

6

Если это фактический сценарий, он должен быть более эффективным, чтобы избавиться от обработки PL/SQL и просто делать все, что в SQL. Массовая обработка в PL/SQL более эффективна, чем обработка строк за строкой в ​​PL/SQL, но SQL более эффективен, чем PL/SQL.

UPDATE table_user_backup tub 
    SET (sirname, sirname_date) = (SELECT sirname, sysdate 
            FROM table_user tu 
            WHERE tu.id = tub.id) 
WHERE EXISTS(SELECT 1 
       FROM table_user 
       WHERE tu.id = tub.id); 

Если этого не достаточно эффективно, вы должны сказать нам, какие индексы доступны, что план запроса, сколько строк участвуют и т.д.

+0

Я делилась можно тремя способами массовое обновление результатов тестирования. –

Смежные вопросы