Jak mogę dodać kolumnę konwersji do dużej tabeli przy minimalnym przestoju?

21

Korzystając z programu SQL Server 2008 i nowszych wersji, chcę dodać kolumnę konwersji wiersza do dużej tabeli, ale kiedy po prostu

ALTER TABLE [Tablename]
ADD Rowversion [Rowversion] NOT NULL

Wtedy tabela nie będzie dostępna dla aktualizacji zbyt długo.

Jakie strategie mogę zastosować, aby skrócić ten czas przestoju? Rozważę wszystko. Im prościej, tym lepiej, oczywiście, ale rozważę każdą strategię.

Myślę, że w ostateczności mogę utrzymać tabelę pomostową kopii obsługiwaną przez wyzwalacze, a następnie sp_rename tabelę pomostową do oryginalnej tabeli. Ale mam nadzieję na coś prostszego / łatwiejszego.

Michael J Swart
źródło

Odpowiedzi:

26

Zastanów się nad utworzeniem nowej tabeli z tym samym schematem i kolumną konwersji wierszy, a także dodaj widok na obu tabelach, który tworzy całość. Niech ludzie używają widoku i piszą zamiast wyzwalaczy względem bazowych tabel i widoków.

Wkładki powinny być wysyłane do nowej tabeli, aktualizacje powinny przenosić dane do nowej tabeli, a usunięcia powinny być stosowane do obu tabel.

Następnie wykonuj ruchy wsadowe w tle, przenosząc jednocześnie tyle rekordów, ile możesz, do nowej tabeli. Nadal możesz mieć problemy z współbieżnością, a także pewne plany wykonania, ale pozwala ci pozostać online podczas wykonywania ruchów.

Najlepiej jest rozpocząć proces w piątek po południu, aby zminimalizować wpływ na użytkowników końcowych i postarać się to zrobić przed poniedziałkiem rano. Kiedy już znajdzie się na miejscu, możesz zmienić widok, tak aby wskazywał tylko na nowy stół, a plany wykonania krytyczne znikają. Idealnie.

Aby uniknąć wyzwalania wyzwalaczy podczas migracji danych partiami, spójrz na liczbę wierszy w usuniętych / wstawionych tabelach wyzwalacza i pomiń działania, jeśli są zbliżone do liczby wierszy w partii.


Na koniec Michael postanowił pominąć widok (i nie usuwać z oryginalnej tabeli), aby uzyskać bardziej stabilne plany. Kompromis obejmował zasadniczo dwie kopie stołu. Przekształcił go w serię postów na blogu .

Brent Ozar
źródło
7

Jeśli masz czas na planowanie, jest o wiele łatwiejsze rozwiązanie ... (zwykle)

Długie blokady są prawie na pewno spowodowane podziałami stron w warstwie pamięci. Wymuś je według własnego harmonogramu.

  1. Dodaj kolumnę tymczasową z możliwością NULL i typem danych VARBINARY(8).
  2. Znajdź dostępny czas luzu w bazie danych, aby zaktualizować partie istniejących rekordów o prawidłową wartość dla pola. ( 0x0000000027F95A5Bna przykład)
  3. Aktualizacje wymuszą niezbędne podziały stron i przydzielą więcej miejsca w tabeli.
  4. Gdy Cię złapiesz, upuść tymczasową kolumnę (nie dotyka przydzielonego miejsca) i dodaj kolumnę konwersji.
  5. Brak podziału strony i blokada, która jest potrzebna tylko na tyle długo, aby wypełnić wartości.

Z powodzeniem wykorzystałem to, aby dodać kolumnę konwersji wiersza do tabeli wierszy 150 mln w niecałe 10 minut.

Zastrzeżenie ... jeśli masz tabelę z dużymi polami varchar (szczególnie varchar(max)) SQL Server decyduje się odbudować tabelę zamiast ponownie wykorzystywać nowo dostępną przestrzeń. Wciąż próbuję znaleźć sposób na obejście tego.

Scott Lynch
źródło
Co ciekawe, chyba nie sprecyzowałem, co w moim pytaniu oznacza „zbyt długo”. Jeśli> 30 minut jest za długie dla twojego scenariusza, a 10 minut jest do zaakceptowania, to rozwiązanie zadziałałoby. Mój scenariusz polegał na próbie osiągnięcia zerowego czasu przestoju, a dokładniej <10 sekund, co osiągnięto dzięki odpowiedzi Brenta.
Michael J Swart
1

Jeśli TIMESTAMPdodajesz to NULLABLE:

  1. Dodaj VARBINARY(8)kolumnę
  2. Wypełnij danymi.

Po to jest wypełniane, w powrotem do tyłu SQL, kolumna po prostu dodaje zaludnionych i dodaj kolumnę.DROPVARBINARY(8)TIMESTAMP NULL


Jeśli TIMESTAMPdodajesz to NOT NULLABLE:

  1. Dodaj BINARY(8)kolumnę
  2. Wypełnij danymi.

Po to jest wypełniane, w powrotem do tyłu SQL, kolumna po prostu dodaje zaludnionych i kolumna.DROPBINARY(8)ADD THE TIMESTAMP NOT NULL

Paul White mówi GoFundMonica
źródło