Zaktualizuj wszystkie wiersze

12

Chcę poznać najbardziej efektywny sposób aktualizowania każdego wiersza w bardzo dużej tabeli Oracle dla jednej kolumny. Na przykład:

update mytable set mycolumn=null;

lub:

update mytable set mycolumn=42;

Moja wiedza może być bardzo nieaktualna. To, co robię, to zmieniam tabelę, aby upuścić kolumnę. Następnie zmieniam tabelę, aby dodać kolumnę z domyślną wartością nowej wartości, której chcę użyć. Następnie zmieniam tabelę, aby usunąć domyślną wartość dla kolumny. Uważam, że jest to o wiele szybsze niż uruchamianie aktualizacji, ale mam wrażenie, że istnieje lepsza metoda.

kainaw
źródło
O ile rozumiem, dodanie nowej niezerowej kolumny z wartością domyślną jest tylko zmianą metadanych w Oracle. Wątpię, aby zoptymalizowali przypadek „zaktualizuj wszystkie wiersze do tej samej wartości”. Czy to jest dla ciebie wspólna operacja?
Martin Smith
1
Po prostu wypróbuj obie metody i zmierz ich czas. Co powstrzymuje cię przed zrobieniem tego? Oto fakt, że musisz zakończyć z tym samym rezultatem, a nie innym wynikiem! W przeciwnym razie porównanie jest nieprawidłowe.
tvCa
@tvCa Próbowałem w obie strony. Jeśli tylko zrobię aktualizację, będzie ona działać przez około dwie godziny, a następnie ją zabiję. Jeśli upuszczę kolumnę, zajmie to tylko kilka sekund. Dodanie kolumny bez wartości domyślnej (która zeruje kolumnę) zajmuje tylko kilka sekund. Dodanie kolumny z wartością domyślną zajmuje około 30 minut. Tak więc, jeśli chcę na przykład ustawić wszystkie wartości w kolumnie na „Some Value”, obecnie upuszczam i dodaję kolumnę. Chcę tylko wiedzieć, czy jest na to szybszy sposób.
kainaw
2
Czy używasz 11gR2? @MartinSmith jest poprawny. Zobacz tutaj, w jaki sposób dodanie nowej kolumny z DOMYŚLNYM jako NIE NULL jest zmianą znacznie szybszą niż dodanie jej jako NULL, co wymusi aktualizację wszystkich wierszy w tabeli (podobnie jak wyda instrukcję UPDATE). Problem, który widzę, polega na usunięciu wartości DOMYŚLNEJ później, ponieważ wzrost wydajności wynika z zapisywania DOMYŚLNEJ w słowniku. W tym momencie będziesz musiał poradzić sobie z ograniczeniem NOT NULL.
ansible

Odpowiedzi:

2

Wiele zależy od innych działań wykonywanych przeciwko tej tabeli podczas wykonywania tej masowej aktualizacji. Mam nadzieję, że masz jakieś środowisko testowe, w którym możesz uruchomić próbki tego, co chcesz zrobić i dowiedzieć się, który sposób jest najlepszy. Spróbowałbym:

  1. Uruchom singiel update table set column_name = blah;
  2. Utwórz pętlę plSql, aby wybrać wszystkie klucze podstawowe w tabeli i przejść przez nie, updating the column=blaha także zatwierdzać każdą aktualizację X (być może 10000). Możesz zrównoleglić ten kod, kopiując go i kopiując, wykonując osobną sekcję kluczy podstawowych.

Mieliśmy bardzo podobny problem z tabelą, która była bardzo aktywnie wykorzystywana w systemie OLTP i byliśmy w stanie zrównoleglić ją 5 razy i działaliśmy bez wpływu użytkownika na blokowanie tabeli wierszy o wielkości 100+ MM co 10000. Nie powiedziałeś, jak duży stół lub rodzaj aplikacji, którą uruchamiasz, ale tego rodzaju rozwiązanie może ci pasować.

Pete Hagerty
źródło
0

Aby szybko UPDATE, upewnij się, że nie masz żadnych wyzwalaczy, które strzelają.

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

ALTER TABLE mytable DISABLE ALL TRIGGERS;

Pamiętaj, aby ponownie włączyć tylko te, które chcesz, kiedy skończysz.

ALTER TRIGGER mytrigger ENABLE;

Być może natrafiłeś na ogólne koszty utrzymania indeksu. Spróbuj odbudować swoje indeksy osobno. Aby to zrobić, pomocna tutaj odpowiedź pappes powinna być pomocna: /programming/129046/disable-and-later-enable-all-table-indexes-in-oracle

Powtarzam tutaj odpowiedź pappe w celach informacyjnych. (Pamiętaj, że to polecenie SPOOL przyjmuje założenia dotyczące platformy i środowiska).

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

Importuj ...

select 'alter index ' || u.index_name || ' rebuild online;'
  from user_indexes u;
durette
źródło
-1

usuń indeks. zaktualizuj kolumnę. zwróć indeks z powrotem. ale jeśli kolumna zawiera tę samą wartość dla wszystkich wierszy, możesz usunąć indeks.

tatskie
źródło
-2

Jeśli nie masz ograniczenia miejsca, możesz utworzyć nową tabelę, taką samą jak twoja tabela z nową kolumną dodaną do tej tabeli i usunąć starą tabelę:

create new_table as
select old_table.*, (with or without default_Value) as new_column
from old_table;
E_Salamon
źródło
1
Czy to będzie bardziej wydajne? Dlaczego? A jeśli istnieją FK, które odwołują się do istniejącej tabeli?
ypercubeᵀᴹ
tak, możesz wypróbować go na innej przykładowej tabeli i sam zobaczyć wynik. Jeśli są FK, nie wiem dokładnie, ale możesz je wyłączyć i włączyć, jeśli jest wydajne.
E_Salamon
-3

Wypróbuj wiele sekwencji aktualizacji / zatwierdzania. Wstawianie / aktualizowanie / usuwanie zbyt wielu wierszy bez zatwierdzenia prowadzi do dużego obciążenia operacji we / wy. Można go dość zoptymalizować, znając rozmiary bloków oraz rozmiary rekordów i inne rzeczy.

Do usuwania całych danych z tabeli truncate table xjest lepsze niż delete from x. Również czyszczenie powoduje kolejne obciążenie procesu.

Edycja: Możesz użyć inmemoryopcji, ładując tabelę do pamięci w formacie kolumnowym, a następnie wykonać aktualizację. to naprawdę zależy od relacji i struktury twojego DB. Zobacz ten artykuł .

Przebiegły
źródło
3
Chcą zaktualizować jedną kolumnę tabeli. Nie rozumiem, w jaki sposób truncateani deletenie miałbym żadnej pomocy.
ypercubeᵀᴹ
@ypercube Właśnie wyjaśniłem, w jaki sposób manipulowanie wieloma danymi bez zatwierdzenia prowadzi do niechcianego ładowania IO; bądź aktualizacją lub innymi OLTP.
Przebiegłość,
3
Czy możesz wyjaśnić, jak częste zatwierdzenia zmniejszają operacje wejścia / wyjścia? Czy nie zwiększyliby We / Wy z powodu punktów kontrolnych?
mustaccio
3
Używanie niekonwencjonalnej terminologii („tx journal”, „opróżnia sesję”) jest nieco mylące. Bez względu na to, czy używasz wielu krótkich transakcji, czy jednej masowej transakcji, łączna wielkość wygenerowanych rekordów powtórzeń będzie taka sama. Operacje we / wy występują tylko wtedy, gdy bufor dziennika powtórzeń jest zapisywany na dysku (na razie pozostawia same punkty kontrolne pamięci podręcznej bufora), co dzieje się po zatwierdzeniu lub gdy bufor ponownego wykonywania jest prawie pełny. Następnie, jeśli często się popełniasz, powodujesz dodatkowe wejścia / wyjścia, więc zastanawiam się, jak to może zmniejszyć liczbę wejść / wyjść.
mustaccio
4
Być może zechcesz przeczytać, co Tom Kyte ma do powiedzenia na temat „częstych zmian ”: asktom.oracle.com/pls/apex/…jest źle, źle, źle. Tak źle .... Tak bardzo bardzo źle
a_horse_with_no_name