UPDATE большого количества записей

Anross

Добрый день, есть таблица T в которой шесть миллионов записей. В таблице есть внешний ключ на справочник. В справочнике надо поменять ИД с одного на другой, используя таблицу соответствий. Если я правильно понимаю, просто обновление ИД в справочнике будет очень долгим, так как после каждого будет перестраиваться индекс. Поэтому я отключаю CONSTRAINT внешнего ключа в таблицe T и прогоняю скрипт типа:
BEGIN
    FOR rec IN (SELECT old_id, new_id FROM decode_table)
    loop
        UPDATE TABLE
        SET foreign_id=new_id
        WHERE foreign_id=old_id;
    END loop;
END;
Но сие так же выполняется часы. А нужно в идеале минут 10, так как есть еще схожие таблицы. В чем проблема такой низкой скорости выполнения? Как сделать быстрее?
3 ответа

Anross

Используйте курсор, это должно увеличить производительность.Как-то так
DECLARE
    CURSOR get_id IS
        SELECT old_id, new_id FROM decode_table;
    v_gid get_id%ROWTYPE;
BEGIN
    OPEN get_id;
    LOOP
        FETCH get_id INTO v_gid;
        EXIT WHEN get_id%NOTFOUND;
        UPDATE TABLE
            SET foreign_id=v_gid.new_id
            WHERE foreign_id=v_gid.old_id;
    END LOOP;
    CLOSE get_id;
END;
Чуть проще
DECLARE
    CURSOR get_id IS
        SELECT old_id, new_id FROM decode_table;
BEGIN
FOR v_gid IN get_id LOOP
        UPDATE TABLE
            SET foreign_id=v_gid.new_id
            WHERE foreign_id=v_gid.old_id;
    END LOOP;
END;
Еще вариант
DECLARE 
cursor get_id IS SELECT t.foreign_id,dt.old_id,dt.new_id  FROM decode_table dt, TABLE t WHERE dt.foreign_id=t.old_id FOR UPDATE dt.foreign_id; 
BEGIN 
FOR x IN get_id loop 
UPDATE TABLE
SET TABLE.foreign_id=x.new_id
WHERE TABLE.foreign_id=x.foreign_id;
END loop; 
END;
еще один вариант
BEGIN
    FOR rec IN (SELECT dt.old_id, dt.new_id, t.foreign_id FROM decode_table dt, TABLE t WHERE t.foreign_id=dt.old_id)
    loop
        UPDATE TABLE
        SET TABLE.foreign_id=rec.new_id
        WHERE TABLE.foreign_id=rec.foreign_id;
    END loop;
END;


Anross

Вариант автора ведь тоже курсор только неявный. Интересно получилось ускорить update предложенными вариантами?


Anross

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