Обновить / Создать таблицу из select с изменениями значений столбцов в Oracle 11g (ускорить) - PullRequest
1 голос
/ 11 октября 2019

На работе у нас есть скрипт обновления для некоторой базы данных Oracle 11g, который занимает около 20 часов, и некоторые из самых требовательных запросов - это обновления, в которых мы изменяем некоторые значения, например:

UPDATE table1 SET
    column1 = DECODE(table1.column1,null,null,'no info','no info','default value'),
    column2 = DECODE(table1.column2,null,null,'no info','no info','another default value'),
    column3 = 'default value';

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

Мой подход заключается в воссоздании таблицы (как сказал TOM в https://asktom.oracle.com/pls/asktom/f?p=100:11:0::NO::P11_QUESTION_ID:6407993912330). Но я понятия не имею, как извлечь некоторые столбцы из исходной таблицы, которые останутся прежними, а также другие, которые изменятся на значение по умолчанию (и до обновления у такого столбца была разумная информация), потому чтонам нужно сохранить некоторую информацию в секрете.

Итак, мой подход примерно такой:


CREATE TABLE table1_tmp PARALLEL NOLOGGING
    AS (select col1,col2,col3,col4 from table1);

ALTER TABLE table1_tmp ADD ( col5 VARCHAR(10) default('some info') NOT NULL;
ALTER TABLE table1_tmp ADD ( col6 VARCHAR(10) default('some info') NOT NULL;

ALTER TABLE table1_tmp ADD ( col7 VARCHAR(10);
ALTER TABLE table1_tmp ADD ( col8 VARCHAR(10);
MERGE INTO table1_tmp tt
    USING table1 t
    ON (t.col1 = tt.col1)
WHEN MATCHED THEN
    UPDATE SET
        tt.col7 = 'some defaul value that may be null',
        tt.col7 = 'some value that may be null';

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

Надеюсь, у вас есть представление о том, как улучшить производительность в подобных вещах. Заранее спасибо!

Ответы [ 2 ]

1 голос
/ 21 октября 2019

Может быть, вы можете попробовать использовать NVL при объединении в объединение:

MERGE INTO table1_tmp tt
    USING table1 t
    ON (nlv(t.col1,'-3') = nvl(tt.col1,'-3'))
WHEN MATCHED THEN ....

Если вы не хотите обновлять нулевые значения, вы также можете сделать это так:

MERGE INTO table1_tmp tt
    USING table1 t
    ON (nlv(t.col1,'-3') = nvl(tt.col1,'-2'))
WHEN MATCHED THEN .....
0 голосов
/ 22 октября 2019

В конце я закончил создание временной таблицы с данными из исходной таблицы, и во время создания, вставки значений по умолчанию, декодирования и любых других вещей, например, если я хотел установить значение NULL, я сделалбросать. Что-то вроде:

    CREATE TABLE table1_tmp AS (
        column1 default "default message",
        column2, --This column with no change at all
        column3, --This will take the value from the decode below 
     ) AS SELECT 
        "default message" column1,
        column2 --This column with no change at all,
        decode(column3, "Something", NULL, "A", "B") column3,
     FROM table1;

Вот так я решил проблему. Время обработки таблицы с 23 миллионами строк составляло от 3 до 5 минут, а обновление занимало часы. Теперь просто нужно установить привилегии, ограничения, индексы, комментарии и все, но это занимает всего несколько секунд.

Спасибо за ответ @thehazal не смог проверить ваш подход, но звучит интересно.

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