Po pierwsze, dziękuję za zrobienie tego. Jest to tak oczywista wygrana, że wielu nie dostrzegłoby w niej dużej wartości, ale będzie warto :). Sprawiamy, że świat staje się trochę zdrowszy.
Odnośnie IsActive
bycie wartością logiczną. Domyślam się, że myślisz o uczynieniu z tego BIT
pole. To może być droga, ale czasami lepiej jest użyć TINYINT
ponieważ istnieje możliwość rozszerzenia znaczenia na więcej niż 2 stany. W takim przypadku naprawdę staje się bardziej z StatusID
. Zwykle jest to przypadek, gdy coś zaczyna się w uproszczeniu jako Aktywne / Nieaktywny , ale później może usunięte i/lub inne. Z perspektywy rozmiaru TINYINT
ma zawsze 1 bajt. Z drugiej strony BIT
wynosi 1 bajt do 8 BIT
pola . Znaczenie, jeden BIT
pole to 1 bajt, 2 BIT
pola to również jeden bajt i tak dalej aż do 8 BIT
pola są przechowywane w jednym bajcie. Tak więc nie ma oszczędności miejsca, wybierając BIT
ponad TINYINT
gdy tabela ma tylko 1 BIT
pole. Po prostu coś do rozważenia.
Jak widzieliście, zrobienie ALTER TABLE to trochę za dużo jak na duży stół. Jedną z opcji, choć niezbyt dobrą, jest dodanie NOT NULL
pole--Number_1new
--z DEFAULT
wartość (będzie to natychmiastowe ze względu na domyślną, przynajmniej począwszy od SQL 2012), której żaden z nich nie miałby naturalnie (np. 255), a następnie powoli migruje wartości, w pętli, jak w:
UPDATE TOP (5000) tab
SET tab.Number_1new = tab.Number_1
FROM [table] tab
WHERE tab.Number_1new = 255;
A kiedy to zrobisz, wykonaj:
sp_rename 'table.Number_1', 'Number_1old', 'COLUMN';
sp_rename 'table.Number_1new', 'Number_1', 'COLUMN';
Oczywiście najlepiej zapakować to w TRANSAKCJĘ, a to w TRY/CATCH. Gdy powiązany kod zostanie zaktualizowany i wszystko przetestowane, a dane wyglądają dobrze, możesz usunąć Number_1old
kolumna.
Jednak najlepszym sposobem, jaki znalazłem, jest utworzenie nowej tabeli, powolne przeniesienie danych, a następnie zamiana tabel i kodu w tym samym czasie. Opisałem kroki w artykule na temat SQL Server Central:Restrukturyzacja 100 milionów wierszy (lub więcej) Tabele w sekundach. SRSLY! (wymagana bezpłatna rejestracja). Na wypadek, gdyby pojawiły się problemy z dotarciem do tego artykułu, oto podstawowe kroki:
- Utwórz nową tabelę o idealnej strukturze — [tableNew]. Jeśli korzystasz z Enterprise Edition, rozważ włączenie kompresji ROW lub PAGE, ponieważ czasami mogą one pomóc. Ale najpierw zrób trochę badań, ponieważ zdarzają się sytuacje, w których mają one negatywny wpływ. W witrynie MSDN dostępna jest dokumentacja, która pomoże Ci to rozgryźć, a także niektóre narzędzia pomagające oszacować potencjalne oszczędności. Ale nawet jeśli włączysz kompresję, nie postrzegałbym tej akcji jako zastąpienia projektu, który tutaj robisz.
- Dodaj wyzwalacz
AFTER UPDATE, DELETE
na [table], aby zachować synchronizację zmian (ale nie musisz się martwić o nowe wiersze) - Utwórz zadanie agenta SQL, które partiami przenosi brakujące wiersze. Zrób to w pętli, która wykonuje
INSERT INTO [tableNew] (Columns) SELECT TOP (n) Columns FROM [table] WHERE ?? ORDER BY ??
- Klauzule WHERE i ORDER BY zależą od sytuacji. Powinny być nastawione na jak najlepsze wykorzystanie indeksu klastrowego. Jeśli indeks klastrowy nowej tabeli jest strukturalnie taki sam jak stara/bieżąca tabela, to na początku każdej pętli możesz uzyskać MAX([id]) z [tableNew] i użyć go do pobrania tabeli
WHERE table.[id] > @MaxIdInTableNew ORDER BY table.[id]
. - Utwórz nową tabelę, wyzwalacz w bieżącej tabeli i zadanie SQL Agent mniej więcej tydzień przed wykonaniem pełnego przełączenia. Te ramy czasowe mogą się zmienić w zależności od Twojej sytuacji, ale pamiętaj, aby dać sobie dużo czasu. O wiele lepiej jest zakończyć migrację wierszy i mieć tylko kilka ściekających naraz, niż być 100 tys.
- Jeśli plan zakłada migrację innych powiązanych tabel (odniesienia PK dla dwóch FK, które chcesz przekształcić w
INT
s), a następnie utwórz te pola tutajINT
teraz i po prostu nie dodawaj FK, dopóki te inne tabele nie zostaną przeniesione do pól INT jako ich PK. Nie chcesz ponownie przebudowywać tej tabeli tylko po to, aby wprowadzić tę zmianę w polach FK. - Podczas odcięcia (oczywiście w TRY / CATCH):
- ROZPOCZNIJ TRANSFER
- wykonaj ostateczną liczbę wierszy na obu tabelach, aby upewnić się, że wszystko zostało przeniesione (może chcieć sprawdzić poprawność wierszy przed wydaniem, aby upewnić się, że wyzwalacz wykonał aktualizacje i usunięcia zgodnie z oczekiwaniami)
- zmień nazwę bieżącej tabeli na „starą”
- zmień nazwę „nowej” tabeli, aby nie miała „nowej”
- upuść zadanie agenta SQL (lub przynajmniej wyłącz je)
- zmień nazwę i obiekty zależne, takie jak ograniczenia itp.
- POTWIERDZENIE