Dodawanie kolumn do tabel produkcyjnych

28

Jaki jest najlepszy sposób dodawania kolumn do dużych tabel produkcyjnych w SQL Server 2008 R2? Według książek Microsoftu online:

Zmiany określone w ALTER TABLE są wdrażane natychmiast. Jeśli zmiany wymagają modyfikacji wierszy w tabeli, ALTER TABLE aktualizuje wiersze. ALTER TABLE uzyskuje blokadę modyfikacji schematu w tabeli, aby upewnić się, że żadne inne połączenia nie odwołują się nawet do metadanych tabeli podczas zmiany, z wyjątkiem operacji indeksu online, które wymagają bardzo krótkiej blokady SCH-M na końcu.

(http://msdn.microsoft.com/en-us/library/ms190273.aspx)

Na dużym stole z milionami rzędów może to chwilę potrwać. Czy wyłączenie jest jedyną opcją? Jaki jest najlepszy sposób poradzenia sobie z tego rodzaju sytuacją?

sh-beta
źródło
1
Ostatni artykuł dotyczący tego problemu: sqlservercentral.com/articles/Change+Tracking/74397
8kb

Odpowiedzi:

27

"To zależy"

Jeśli dodasz kolumnę, która nie wymaga dodawania danych do wierszy, może to być dość szybkie.

Na przykład dodanie int lub char wymaga fizycznych ruchów wiersza. Dodanie nullable varchar bez domyślnej wartości nie powinno (chyba że bitmapa NULL wymaga rozwinięcia)

Musisz wypróbować go na przywróconej kopii produkcji, aby uzyskać oszacowanie

Tworzenie nowej tabeli, kopiowanie, zmiana nazwy może potrwać dłużej, jeśli będziesz musiał ponownie dodać indeksy i klucze do tabeli o miliardach wierszy.

Zmieniłem miliardy tabel wierszy, które zajęły kilka sekund, aby dodać kolumnę zerowalną.

Czy najpierw powiedziałem, żeby zrobić kopię zapasową?

gbn
źródło
2
+1 na kopii zapasowej. i upewnij się, że masz wystarczająco dużo miejsca w dzienniku.
SqlACID
Czy możesz wyjaśnić, dlaczego dodanie int lub char wymaga fizycznych ruchów wierszy?
sh-beta,
5
Czy chodziło Ci o to, że „nie” wymaga dodania danych do wierszy w drugim wierszu?
Ben Brocka
21

Jeśli kolumna ma wartość NULLable, wpływ powinien być znikomy. Jeśli kolumna nie może mieć wartości NULL, a wartość musi być ustawiona, może być zupełnie inna. W tym przypadku zrobiłbym to zamiast dodawać ograniczenie niewymienne i domyślne w jednym ujęciu, skutecznie dodając dane do każdego wiersza:

  • dodaj kolumnę jako NULLable - w większości przypadków powinna być szybka
  • zaktualizuj wartości do wartości domyślnych
    • w razie potrzeby możesz to zrobić partiami
    • możesz również użyć tego do zastosowania logiki warunkowej, w której niektóre wiersze mogą nie otrzymać wartości domyślnej
  • dodaj ograniczenia inne niż null / default
    • będzie to szybsze, gdy żadne z danych nie będzie miało wartości NULL, ale nadal powinno być mierzalne

Zgadzam się z @gbn, że możesz to przetestować, przywracając kopię produkcji i wypróbowując ją tam ... dostaniesz dobry pomysł na czas (zakładając, że sprzęt jest nieco podobny), a także zobaczysz wpływ na dziennik transakcji.

Aaron Bertrand
źródło
Re ostatnia •add the not null/default constraintskwestia : nie jestem pewien, czy nie ma z tym potencjalnego problemu ... Gdy MSSQL (nawet 2008R2) zmieni kolumnę niepustą na null, jeśli zaznaczysz ślad, zobaczysz go pod przykryciem wykonuję pełną aktualizację każdego wiersza tabeli, tzn. update table1 set column1 = column1zakładam, że dokonuje weryfikacji non-null w całkowicie idiotyczny sposób. Ta transakcja jest dwa razy większa niż tabela (przed i po stronach), więc dla tabeli DW może być ogromna. Wcześniej musieliśmy wydobywać dane z komputera, obcinać je, wprowadzać zmiany od zera do wartości innej niż null, a następnie bcp.
Jeśli ktoś wie, jak to obejść, uwielbiam wiedzieć ... Natomiast w Oracle zmiana wartości null na non null powoduje blokadę, a następnie wybranie opcji sprawdzenia, czy nie ma wartości null, a następnie natychmiastowa aktualizacja czysto metadanych.
Hej @ Mike, to brzmi jak samo dobre potencjalne pytanie.
Derek Downey
4

Czy rozważałeś:

  1. Tworzenie nowej tabeli, która zawiera zmiany w definicji tabeli.
  2. Wstawianie do nowej definicji tabeli wybierając z oryginalnej tabeli.
  3. Zmiana nazwy oryginalnej tabeli na _orig, a następnie zmiana nazwy nowej tabeli na pierwotną nazwę tabeli.

Wadą jest to, że musisz mieć wystarczającą ilość miejsca w bazie danych, aby dokonać tej zmiany. Nadal możesz wymagać blokady odczytu na stole, aby zapobiec brudnym odczytom.

Jednak minimalizujesz wpływ na użytkowników końcowych, jeśli istnieje szansa lub potrzeba jednoczesnego dostępu do oryginalnej tabeli. Powinien także minimalizować czas trwania blokady.

RobPaller
źródło
Czy nie potrzebujesz blokady zapisu zamiast czytać? Użytkownicy mogą widzieć dane w starej tabeli, po prostu nie chcesz, aby dokonywali jakichkolwiek zmian, które zostałyby nadpisane po zakończeniu wymiany bufora.
Jon of All Trades,
Tak myślałem z kapeluszem hurtowni danych, gdzie zmiany można nieco łatwiej kontrolować. W sytuacji OLTP masz rację, blokada zapisu byłaby konieczna, aby uniknąć wprowadzania zmian w tabeli.
RobPaller,