Оновити всі рядки


12

Я хочу знати найефективніший спосіб оновлювати кожен рядок у надзвичайно великій таблиці Oracle для одного стовпця. Наприклад:

update mytable set mycolumn=null;

або:

update mytable set mycolumn=42;

Мої знання цілком можуть бути несвіжими. Що я роблю, це змінити таблицю, щоб скинути стовпчик. Потім я змінюю таблицю, щоб додати стовпець зі значенням за замовчуванням нового значення, яке я хочу використовувати. Потім я змінюю таблицю, щоб видалити значення за замовчуванням для стовпця. Я вважаю, що це набагато швидше, ніж просто запускати оновлення, але у мене є відчуття, що є кращий метод.


Наскільки я розумію, додавання нового ненульового стовпця із замовчуванням - це зміна метаданих лише в Oracle. Я сумніваюся, що вони оптимізували б "оновити всі рядки до одного значення". Це звичайна для вас операція?
Мартін Сміт

1
Просто спробуйте обидва методи та час їх. Що заважає вам це робити? Ось факт, що ви повинні закінчитися тим самим результатом, а не іншим результатом! В іншому випадку порівняння недійсне.
tvCa

@tvCa Я пробував обидва способи. Якщо я просто оновлюю, воно працює близько двох годин, а потім я його вбиваю. Якщо я скину стовпчик, це займе лише кілька секунд. Додавання стовпця без значення за замовчуванням (що скасовує стовпець) займає лише кілька секунд. Додавання стовпця зі значенням за замовчуванням займає близько 30 хвилин. Отже, якщо я хочу, наприклад, встановити всі значення в стовпці на "деяке значення", я в даний час скидаю і додаю стовпець. Я просто хочу знати, чи існує швидший спосіб зробити це.
kainaw

2
Ви використовуєте 11gR2? @MartinSmith правильний. Ознайомтесь з описом того, як додавання нового стовпця за допомогою DEFAULT як NOT NULL - це набагато швидша зміна, ніж додавання його як NULL, що змусить оновити всі рядки таблиці (так само, як видавати оператор UPDATE). Я бачу проблему - видалити значення DEFAULT після цього, оскільки підвищення продуктивності відбувається від зберігання DEFAULT у словнику. Вам також доведеться мати справу з обмеженням NOT NULL у цій точці.
ansible

Відповіді:


2

Багато що залежить від іншої діяльності, що відбувається проти цієї таблиці, коли ви робите це масове оновлення. Я сподіваюся, що у вас є якесь тестове середовище, де ви можете запустити кілька зразків того, що ви хочете зробити, і зрозуміти, який спосіб найкращий. Я б спробував:

  1. Виконати сингл update table set column_name = blah;
  2. Створіть цикл plSql, щоб вибрати всі первинні ключі в таблиці та прокрутити їх, updating the column=blahа також здійснювати кожне оновлення X (можливо, 10000). Ви можете паралелізувати цей код, скопіювавши його та змусивши його скопіювати зробити окремий розділ Основні ключі.

У нас був дуже подібний випадок із таблицею, яка дуже активно використовувалася в системі OLTP, і ми змогли паралелізувати її 5 разів і запустили, не впливаючи на блокування користувача, на 100+ MM таблиці рядків, здійснюючи кожні 10000. Ви не сказали, як великий ваш стіл або який саме додаток ви працюєте, але таке рішення може вам підійти.


0

Швидко UPDATEпереконайтесь, що у вас немає жодного тригера, який спрацьовує.

SELECT trigger_name, status FROM user_triggers WHERE table_name = 'MYTABLE';

ALTER TABLE mytable DISABLE ALL TRIGGERS;

Не забудьте ввімкнути лише ті, що хочете, коли закінчите.

ALTER TRIGGER mytrigger ENABLE;

Можливо, ви також стикаєтеся з накладними витратами на обслуговування індексу. Спробуйте відновити свої індекси окремо. Для цього корисна відповідь тут від папп: /programming/129046/disable-and-later-enable-all-table-indexes-in-oracle

Я повторюю тут відповідь паппе для довідки. (Зверніть увагу, що ця команда SPOOL робить припущення щодо вашої платформи та оточення.)

set pagesize 0    
alter session set skip_unusable_indexes = true;
spool c:\temp\disable_indexes.sql
select 'alter index ' || u.index_name || ' unusable;' from user_indexes u;
spool off
@c:\temp\disable_indexes.sql

Імпортувати ...

select 'alter index ' || u.index_name || ' rebuild online;'
  from user_indexes u;

-1

видалити індекс. оновити стовпчик. повернути індекс назад. але якщо стовпець містить одне і те ж значення для всіх рядків, ви можете скинути індекс.


-2

Якщо у вас немає обмеження на простір, ви можете створити нову таблицю, аналогічну вашій таблиці з новим стовпцем, доданим до цієї таблиці, і видалити стару таблицю:

create new_table as
select old_table.*, (with or without default_Value) as new_column
from old_table;

1
Чи буде це більш ефективно? Чому? А що робити, якщо є FK, які посилаються на існуючу таблицю?
ypercubeᵀᴹ

так, ви можете спробувати його на іншій вибірковій таблиці та побачити результат самостійно. Якщо є FK, я точно не знаю, але ви можете відключити та включити їх, якщо це ефективно.
E_Salamon

-3

Спробуйте кілька послідовностей оновлення / фіксації. Вставлення / оновлення / видалення занадто багато рядків без комірок призводить до великого навантаження вводу-виводу. Це може бути досить оптимізовано, знаючи розміри блоків та розміри запису та інше.

Для видалення цілих даних з таблиці truncate table xкраще, ніж delete from x. Також продувка призводить до іншого робочого навантаження.

Редагувати: Ви можете скористатися inmemoryопцією, завантажуючи таблицю в пам'ять у стовпчастому форматі, а потім виконати оновлення. це дійсно залежить від відносин та структури вашого БД. Дивіться цю статтю .


3
Вони хочуть оновити один стовпчик таблиці. Я не бачу, як truncateчи не deleteмогла б допомогти.
ypercubeᵀᴹ

@ypercube Я щойно пояснив, як багаторазова обробка даних без фіксації призводить до небажаного навантаження вводу-виводу; будь або оновлення або інші OLTP.
Хитрий

3
Чи можете ви пояснити, як часті комісії зменшують введення / виведення? Вони б не збільшували введення-виведення через контрольно-пропускні пункти?
mustaccio

3
Ваше використання нетрадиційної термінології ("tx journal", "промиває ваш сеанс") трохи заплутує. Якщо ви використовуєте кілька коротких транзакцій або одну велику транзакцію, загальний обсяг створених повторних записів буде однаковим. Операції вводу / виводу відбуваються лише тоді, коли буфер журналу повторень записується на диск (поки що залишаються окремі контрольні точки кешу буфера), що відбувається під час фіксації або коли буфер повторень майже заповнений. Згодом, якщо ви здійснюєте часто, ви викликаєте додаткові введення-виведення, тому мені цікаво, як це може зменшити введення-вивід.
мустаччо

4
Ви можете прочитати, що Том Кіт повинен сказати про "часті вчинки ": asktom.oracle.com/pls/apex/… " неправильно, неправильно, неправильно. Так неправильно .... Так дуже сильно неправильно "
a_horse_with_no_name
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.