Jaki jest zalecany rozmiar partii dla SqlBulkCopy?


Odpowiedzi:


97

Mam narzędzie do importowania znajdujące się na tym samym serwerze fizycznym, co moja instancja programu SQL Server. Używając niestandardowego IDataReader, analizuje płaskie pliki i wstawia je do bazy danych przy użyciu SQLBulkCopy. Typowy plik ma około 6 milionów kwalifikowanych wierszy, średnio 5 kolumn dziesiętnego i krótkiego tekstu, około 30 bajtów na wiersz.

Biorąc pod uwagę ten scenariusz, stwierdziłem, że rozmiar partii 5000 jest najlepszym kompromisem między szybkością i zużyciem pamięci. Zacząłem od 500 i eksperymentowałem z większymi. Okazało się, że 5000 jest średnio 2,5 razy szybsze niż 500. Wstawienie 6 milionów wierszy zajmuje około 30 sekund przy wielkości partii 5000 i około 80 sekund przy wielkości partii 500.

10 000 nie było mierzalnie szybsze. Przejście do 50 000 poprawiło prędkość o kilka punktów procentowych, ale nie jest warte zwiększonego obciążenia serwera. Powyżej 50000 nie wykazano poprawy szybkości.

To nie jest formuła, ale to kolejny punkt danych, którego możesz użyć.


3
Należy wziąć pod uwagę, czy tabela jest pusta i zawiera indeksy. W takich przypadkach możesz przesłać wszystko w jednej partii, jak wspomniano tutaj: technet.microsoft.com/en-us/library/ms177445(v=sql.105).aspx "Jeśli zbiorczo importujesz dane do pustej tabeli z indeksami i określisz rozmiar partii, tabela stanie się niepusta po pierwszej partii. Począwszy od drugiej partii, dane są w pełni rejestrowane. W przypadku pustych indeksowanych tabel rozważ wykonanie importu zbiorczego w jednej partii. "
Sal

SqlBulkCopy przesyła strumieniowo dane ze źródła (np. DataTable) do Sql, więc jakie „zwiększone obciążenie serwera” ma w przypadku dużego wsadu? (np. 50 000)
BornToCode

29

Jest to kwestia, nad którą też spędziłem trochę czasu. Chcę zoptymalizować importowanie dużych plików CSV (ponad 16 GB, ponad 65 milionów rekordów i rosnących) do bazy danych SQL Server 2005 przy użyciu aplikacji konsoli C # (.Net 2.0). Jak Jeremy ma już wspomniano , trzeba będzie zrobić kilka dostrojenie do konkretnych okoliczności, ale polecam masz początkową wielkość wsadu 500, a badanie wartości powyżej i poniżej tego.

Otrzymałem zalecenie, aby przetestować wartości od 100 do 1000 dla wielkości partii z tego postu na forum MSDN i byłem sceptyczny. Ale kiedy testowałem partie o wielkości od 100 do 10 000, stwierdziłem, że 500 to optymalna wartość dla mojej aplikacji. Wartość 500 dla SqlBulkCopy.BatchSizezaleca się również tutaj .

Aby jeszcze bardziej zoptymalizować działanie SqlBulkCopy, zapoznaj się z tą poradą MSDN ; Uważam, że użycie SqlBulkCopyOptions.TableLock pomaga skrócić czas ładowania.


Wydaje mi się, że uruchomienie polecenia kopiowania zbiorczego na samym serwerze byłoby prawdopodobnie szybsze.
Kapitan Kenpachi

16

Jak powiedzieli inni, zależy to od środowiska, w szczególności wielkości wiersza i opóźnienia sieci.

Osobiście zacznę od ustawienia BatchSizewłaściwości na 1000 wierszy i zobaczę, jak to działa. Jeśli to zadziała, podwajam liczbę wierszy (np. Do 2000, 4000 itd.), Aż otrzymam limit czasu.

W przeciwnym razie, jeśli przekroczenie limitu czasu nastąpi przy 1000, zmniejszam liczbę wierszy o połowę (np. 500), aż zadziała.

W każdym przypadku podwajam (jeśli się powiedzie) lub zmniejszam o połowę (jeśli się nie udaje) różnicę między każdą z dwóch ostatnich prób wielkości partii, aż do znalezienia idealnego punktu.

Innym czynnikiem, który należy wziąć pod uwagę, jest to, jak długo trwa kopiowanie pojedynczej partii wierszy. Limity czasu wystąpią, jeśli partia kopiowanych wierszy przekroczy BulkCopyTimeoutwłaściwość, która domyślnie wynosi 30 sekund. Możesz spróbować podwoić tę BulkCopyTimeoutwłaściwość do 60 sekund. Pozwala to na skopiowanie większego zestawu wierszy partii przez dłuższy czas. Na przykład partia 50000 wierszy może zająć około 40 sekund po przekroczeniu 30-sekundowego limitu czasu, więc zwiększenie wydajności do 60 sekund może pomóc w zwiększeniu wydajności.


4

Wszystko zależy od Twojej implementacji.

Jakiej prędkości możesz oczekiwać w swojej sieci? Czy używasz go w Forms czy w ASP.Net? Czy musisz ostrzegać użytkownika o postępach? Jaka jest łączna wielkość pracy?

Z mojego doświadczenia wynika, że ​​uruchomienie kopiowania zbiorczego bez określonego rozmiaru partii spowoduje problemy z przekroczeniem limitu czasu. Lubię zaczynać od około 1000 płyt i stamtąd wprowadzać pewne poprawki.


Prędkość: różna, formularze internetowe: tak, ASP.NET: tak, szerokie tabele: tak, wąskie tabele, tak. Tysiące rzędów: tak. Miliony wierszy: tak. Jeśli możesz wymyślić jakiś scenariusz, prawdopodobnie to robię.
Jonathan Allen

1
Muszę więc trzymać się poprzedniej odpowiedzi. Myślę, że nie ma srebrnej kuli.
Jeremy

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.