it-swarm.dev

Dodawanie kolumn do tabel produkcyjnych

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 wykluczenie jest jedyną opcją? Jaki jest najlepszy sposób poradzenia sobie z tego rodzaju sytuacją?

29
sh-beta

"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ą?

27
gbn

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 także użyć tego do zastosowania logiki warunkowej, w przypadku której niektóre wiersze mogą nie otrzymać wartości domyślnej
  • dodaj ograniczenia inne niż null/default
    • będzie to szybsze, gdy żadne dane nie będą miały wartości NULL, ale nadal powinny 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.

21
Aaron Bertrand

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.

4
RobPaller

Mam szczególny wyjątek, który moim zdaniem powinien zostać wymieniony.

W SQL Server 2012 Enterprise i nowszych dodawanie nowej kolumny NOT NULL ze stałą środowiska wykonawczego jest operacją online, która jest wykonywana natychmiast i nie zależy od liczba wierszy w tabeli.

Więcej informacji na ten temat można znaleźć w MSDN

Powielę ważną sekcję

Począwszy od wersji SQL Server 2012 (11.x) Enterprise Edition, dodanie kolumny NOT NULL z wartością domyślną jest operacją online, gdy wartością domyślną jest stała czasu wykonywania. Oznacza to, że operacja jest kończona prawie natychmiast, pomimo liczby wierszy w tabeli. Ponieważ istniejące wiersze w tabeli nie są aktualizowane podczas operacji. Zamiast tego wartość domyślna jest przechowywana tylko w metadanych tabeli, a wartość jest sprawdzana w razie potrzeby w zapytaniach, które uzyskują dostęp do tych wierszy.

1
rince