Muszę zaktualizować 100 milionów rekordów w jednej tabeli, w efekcie normalizując tabelę, zastępując wartość varchar kolumny zwykłym identyfikatorem. (Mówię „zastępuję”, ale tak naprawdę piszę identyfikator w innej kolumnie).
Staram się znormalizować zestaw danych. Dane jeszcze nie znormalizowane nie mają indeksowania. Myślałem, że nie będę budował indeksów na wartościach surowych, czekając, zamiast indeksować klucze obce, które zastąpią wartości varchar wartościami tinyint po zakończeniu aktualizacji.
UPDATE A
SET A.AutoClassID = B.AutoClassID
FROM AutoDataImportStaging.dbo.Automobile as A
JOIN AutoData.dbo.AutoClass as B on (A.AutoClassName = B.AutoClassName)
tło
- za pomocą MSSQL 2008 R2 na Server 2008 R2
- serwer ma 8 GB pamięci RAM
- serwer ma jeden RAID10, 7200 RPM SATA (nie wspaniale, wiem, w produkcji to będzie tylko czytać dane, a nie zapisywać dane; plus niedawny brak HD spowodował, że było to konieczne)
- Serwer ma podwójny czterordzeniowy procesor Xeon
- maszyna nie robi nic innego (obecnie poświęcony programowaniu, tylko ten proces)
- proste logowanie włączone (? - ale czy nadal się loguje, aby móc przywrócić?)
- zwróć uwagę, że zapytanie odwołuje się do dwóch różnych baz danych dla tego, co jest warte
- „szerokość” rekordu w aktualizowanej tabeli wynosi 455 bajtów
Zasoby podczas wykonywania
- fizyczna pamięć RAM jest maksymalna
- dysk we / wy jest maksymalny
- Procesor prawie nic nie robi (dławik to We / Wy)
- czas działania wyniósł 14 godzin i wciąż rośnie!
Podejrzewam kilka rzeczy, takich jak potrzebuję indeksu na surowych danych, nawet jeśli po aktualizacji normalizacji będę upuszczał kolumnę (AutoClassName). Zastanawiam się również, czy powinienem po prostu zapętlać jeden rekord na raz zamiast JOIN, co wydawało się śmieszne w momencie, gdy to zaczynałem, ale teraz wydaje się, że byłoby szybciej.
Jak powinienem zmienić metodologię pozostałych aktualizacji normalizacyjnych (podobnych do tej) szybciej?
źródło
TOP
klauzuli. To byłoby moje podejście.Przyjąłbym inne podejście.
Zamiast aktualizować istniejące tabele, po prostu stwórz nową tabelę, która ma w sobie to, czego potrzebujesz.
Będzie to prawie na pewno szybsze:
Jak obecnie napisano, dzieje się wiele logicznych operacji:
źródło
Zapętlanie stołu po jednym rzędzie na raz nie będzie szybsze!
Jak podejrzewasz i potwierdzasz, będzie to związane we / wy - jeden dysk, odczyt, zapis, dzienniki transakcji i (dowolna) temp. Miejsca pracy będą konkurować o ten sam we / wy.
Proste odzyskiwanie będzie nadal rejestrować transakcje, ale dziennik zostanie wyczyszczony przez punkt kontrolny. Możliwe, że początkowy rozmiar dziennika i ustawienia automatycznego wzrostu powodują pewne spowolnienie operacji we / wy - dziennik transakcji będzie musiał wzrosnąć, aby uwzględnić zmiany.
Czy próbowałeś zaindeksować pole AutoClassName? Ile jest różnych wartości AutoClass?
Konieczne może być grupowanie aktualizacji w zależności od ograniczeń we / wy. Więc zaktualizuj 1 milion, punkt kontrolny, powtórz ....
źródło
Utwórz indeksy dla pól łączących.
Zawsze możesz upuścić indeksy po zakończeniu.
Byłbym bardzo zaskoczony, gdyby indeksy nie poprawiły znacząco wydajności aktualizacji.
źródło
Wyeksportuj tak, jak chcesz, utwórz nową tabelę i zaimportuj ponownie. Jako bonus, będziesz mieć kopię danych jako kopię zapasową, na wypadek cudów.
źródło