Jaki jest najszybszy sposób wstawiania dużej liczby wierszy?

27

Mam bazę danych, w której ładuję pliki do tabeli pomostowej. Z tej tabeli pomostowej mam 1-2 sprzężenia, aby rozwiązać niektóre klucze obce, a następnie wstawiam te wiersze do końcowej tabeli (która ma jedną partycję na miesiąc). Mam około 3,4 miliarda wierszy na trzy miesiące danych.

Jaki jest najszybszy sposób na przeniesienie tych rzędów do stołu finałowego? SSIS Data Flow Task (który używa widoku jako źródła i ma aktywne szybkie ładowanie) lub polecenie Insert INTO SELECT ....? Próbowałem zadania przepływu danych i mogę uzyskać około 1 miliarda wierszy w ciągu około 5 godzin (8 rdzeni / 192 GB pamięci RAM na serwerze), co wydaje mi się bardzo wolne.

nojetlag
źródło
1
Czy partycje na oddzielnych aplikacjach (i znajdują się na tych aplikacjach na różnych dyskach fizycznych)?
Aaron Bertrand
3
Naprawdę dobry zasób Przewodnik po wydajności ładowania danych . Dotyczy to wielu optymalizacji wydajności, które można wykonać, np. Włączanie TF610 , Korzystanie z BCP OUT / IN, SSIS itp. Wystarczy postępować zgodnie z zaleceniami i przetestować je w swoim środowisku.
Kin Shah,
@Aaron tak, miesięcznie jedna grupa plików, dołączone 12 san lun, więc wszyscy Jan idą na jeden lun itp. Nie jestem pewien, ile dysków na lun, ale powinno być wystarczających.
nojetlag
Tak, naprawdę miałem na myśli „zestawy dysków” i prawdopodobnie mógłbym również wspomnieć o kontrolerach, które mogą się nasycić.
Aaron Bertrand
@Kin spojrzał na przewodnik, ale wydaje się nieaktualny: „Miejsce docelowe programu SQL Server to najszybszy sposób na masowe ładowanie danych z przepływu danych Integration Services do programu SQL Server. To miejsce docelowe obsługuje wszystkie opcje masowego ładowania programu SQL Server - z wyjątkiem ROWS_PER_BATCH . ” aw SSIS 2012 zalecają miejsce docelowe OLE DB dla lepszej wydajności.
nojetlag

Odpowiedzi:

25

Jedno wspólne podejście:

  1. Wyłącz / upuść indeksy / ograniczenia w tabeli docelowej.
  2. INSERT dbo.[Target] WITH (TABLOCKX) SELECT ...
  3. Korzystając z JNK, możesz oczywiście zrobić powyższe partie nwierszy, co może zmniejszyć obciążenie dziennika transakcji, i oczywiście oznacza, że ​​jeśli jakaś partia się nie powiedzie, musisz zacząć od tej partii. Napisałem o tym na blogu (chociaż w odniesieniu do usuwania obowiązują te same podstawowe pojęcia) tutaj: http://www.sqlperformance.com/2013/03/io-subsystem/chunk-deletes
  4. Ponownie włącz / ponownie utwórz indeksy / ograniczenia w tabeli docelowej (a być może możesz odroczyć niektóre z nich, jeśli nie są one konieczne do wszystkich operacji, a ważniejsze jest szybkie uzyskanie danych podstawowych online).

Jeśli twoje partycje są fizyczne, a nie tylko logiczne, możesz zyskać trochę czasu, mając różne procesy zapełniające jednocześnie różne partycje (oczywiście oznacza to, że nie możesz użyć TABLOCK/ TABLOCKX). Zakłada się, że źródło jest również odpowiednie do wybierania wielu procesów bez nakładania się / blokowania itp., A także spowalniania tej strony operacji (wskazówka: utwórz indeks klastrowany na źródle, który pasuje do schematu partycjonowania w miejscu docelowym).

Możesz także rozważyć coś o wiele bardziej prymitywnego, na przykład BCP OUT/BCP IN .

Nie wiem, czy skoczyłbym do SSIS, aby pomóc w tym. Prawdopodobnie są tam pewne usprawnienia, ale nie wiem, czy wysiłek uzasadnia oszczędności.

Aaron Bertrand
źródło
2
Nie należy ślepo upuszczać indeksów (zwłaszcza indeks klastrowany), jeśli dane nie są sortowane. Upuszczenie indeksu i oczekiwanie na odtworzenie indeksu klastrowego może być wielkim błędem, ponieważ może kosztować zarówno ogromne miejsce na dysku, jak i ogromną ilość czasu. Nie jestem pierwszym, który doświadczył takiego błędu. Spójrz na opis „Planu B” w tym artykule sqlmag.com/t-sql/… . Autor miał ten sam problem.
jyao 11.04.16
10

Patrząc na twój problem z perspektywy SSIS, wydaje mi się, że powodem, dla którego mogło to zająć tak długo, było to, że nie miałeś wsadu. Może to prowadzić do zbyt dużej liczby wierszy wypełniających potok SSIS i może w rezultacie pogorszyć wydajność SSIS. To, co musisz zrobić, to zmienić ustawienia wierszy na partię i ewentualnie maksymalny rozmiar zatwierdzenia wstawiania. Teraz to, co ustawisz, będzie zależeć od ilości pamięci dostępnej na serwerze SSIS? Jaka jest prędkość dysku twojej instancji SQL Server? Najlepszym sposobem na to jest test. Pozwala na przykład użyć 10.000. Spowoduje to wysłanie partii do serwera 10 000 naraz, dzięki czemu Twój rurociąg nie zostanie przepełniony i pomoże szybciej uruchomić ten proces. Te ustawienia są ustawione w miejscu docelowym OLEDB.

Miejsce docelowe OLEDB

Jeśli jest to problem, możesz dodać zadanie SQL do wykonania przed i po, aby zrobić to, co sugeruje @AaronBertrand i usunąć / ponownie dodać wszelkie indeksy lub ograniczenia do tabeli.

Zane
źródło
1
Istnieje doskonałe pytanie o to, co „szybkie ładowanie” pociąga za sobą gdzie indziej w DBA.SE: dba.stackexchange.com/questions/141430/… .
Jon of All Trades,