Jak badać wydajność instrukcji BULK INSERT?

12

Jestem głównie programistą .NET korzystającym z Entity Framework ORM. Ponieważ jednak nie chcę zawieść przy użyciu ORM , staram się zrozumieć, co dzieje się w warstwie danych (bazie danych). Zasadniczo podczas programowania uruchamiam profiler i sprawdzam, jakie części kodu generują zapytania.

Jeśli zauważę coś bardzo skomplikowanego (ORM może generować okropne zapytania nawet z dość prostych instrukcji LINQ, jeśli nie są starannie napisane) i / lub ciężkie (czas trwania, procesor, odczyty stron), biorę to w SSMS i sprawdzam jego plan wykonania.

Działa dobrze dla mojego poziomu wiedzy o bazie danych. Jednak BULK INSERT wydaje się być specjalnym stworzeniem, ponieważ wydaje się, że nie wytwarza SHOWPLAN .

Spróbuję zilustrować bardzo prosty przykład:

Definicja tabeli

CREATE TABLE dbo.ImportingSystemFileLoadInfo
(
    ImportingSystemFileLoadInfoId INT NOT NULL IDENTITY(1, 1) CONSTRAINT PK_ImportingSystemFileLoadInfo PRIMARY KEY CLUSTERED,
    EnvironmentId INT NOT NULL CONSTRAINT FK_ImportingSystemFileLoadInfo REFERENCES dbo.Environment,
    ImportingSystemId INT NOT NULL CONSTRAINT FK_ImportingSystemFileLoadInfo_ImportingSystem REFERENCES dbo.ImportingSystem,
    FileName NVARCHAR(64) NOT NULL,
FileImportTime DATETIME2 NOT NULL,
    CONSTRAINT UQ_ImportingSystemImportInfo_EnvXIs_TableName UNIQUE (EnvironmentId, ImportingSystemId, FileName, FileImportTime)
)

Uwaga: żadne inne indeksy nie są zdefiniowane w tabeli

Wkładka luzem (co łapię w profilerze, tylko jedna partia)

insert bulk [dbo].[ImportingSystemFileLoadInfo] ([EnvironmentId] Int, [ImportingSystemId] Int, [FileName] NVarChar(64) COLLATE Latin1_General_CI_AS, [FileImportTime] DateTime2(7))

Metryka

  • Wstawiono 695 elementów
  • CPU = 31
  • Odczytuje = 4271
  • Zapisuje = 24
  • Czas trwania = 154
  • Łączna liczba tabel = 11500

W przypadku mojej aplikacji jest to w porządku, chociaż odczyty wydają się dość duże (niewiele wiem o wewnętrznym SQL Server, więc porównuję do wielkości strony 8K i informacji o małym rekordzie, które mam)

Pytanie: jak mogę sprawdzić, czy ten WKŁAD BULK można zoptymalizować? Czy to nie ma sensu, ponieważ jest to prawdopodobnie najszybszy sposób na wypchnięcie dużych danych z aplikacji klienckiej do SQL Server?

Aleksiej
źródło

Odpowiedzi:

14

O ile mogę powiedzieć, możesz zoptymalizować wkładkę zbiorczą w bardzo podobny sposób, jak w przypadku zwykłej wkładki. Zazwyczaj plan zapytań dla prostej wstawki nie jest zbyt pouczający, więc nie martw się o brak planu. Omówię kilka sposobów optymalizacji wkładki, ale większość z nich prawdopodobnie nie dotyczy wkładki określonej w pytaniu. Mogą być jednak pomocne, jeśli w przyszłości będziesz musiał załadować większe ilości danych.

1. Wstaw dane w kolejności kluczy klastrowych

SQL Server często sortuje dane przed wstawieniem ich do tabeli z indeksem klastrowym. W przypadku niektórych tabel i aplikacji można poprawić wydajność, sortując dane w pliku płaskim i informując SQL Server, że dane są sortowane według ORDERargumentu BULK INSERT:

ZAMÓWIENIE ({kolumna [ASC | DESC]} [, ... n])

Określa sposób sortowania danych w pliku danych. Wydajność importu zbiorczego poprawia się, jeśli importowane dane są sortowane zgodnie z indeksem klastrowym w tabeli, jeśli taki istnieje.

Ponieważ używasz IDENTITYkolumny jako klucza klastrowanego, nie musisz się tym martwić.

2. Użyj, TABLOCKjeśli to możliwe

Jeśli masz gwarancję, że tylko jedna sesja wstawi dane do tabeli, możesz podać TABLOCKargument BULK INSERT. Może to zmniejszyć rywalizację o blokadę i może prowadzić do minimalnego logowania w niektórych scenariuszach. Jednak wstawiasz do tabeli z indeksem klastrowym, który już zawiera dane, więc nie uzyskasz minimalnego rejestrowania bez flagi śledzenia 610, o której mowa w dalszej części tej odpowiedzi.

Jeśli TABLOCKnie jest to możliwe, ponieważ nie można zmienić kodu , nie wszystko stracone. Rozważ użycie sp_table_option:

EXEC [sys].[sp_tableoption]
    @TableNamePattern = N'dbo.BulkLoadTable' ,
    @OptionName = 'table lock on bulk load' , 
    @OptionValue = 'ON'

Inną opcją jest włączenie flagi śledzenia 715 .

3. Użyj odpowiedniego rozmiaru partii

Czasami będziesz mógł dostroić wstawki, zmieniając rozmiar partii.

ROWS_PER_BATCH = wiersze_z_badą

Wskazuje przybliżoną liczbę wierszy danych w pliku danych.

Domyślnie wszystkie dane w pliku danych są wysyłane do serwera jako pojedyncza transakcja, a liczba wierszy w partii jest nieznana optymalizatorowi zapytań. Jeśli podasz ROWS_PER_BATCH (o wartości> 0), serwer użyje tej wartości do zoptymalizowania operacji importu zbiorczego. Wartość określona dla ROWS_PER_BATCH powinna być w przybliżeniu taka sama jak faktyczna liczba wierszy. Aby uzyskać informacje dotyczące zagadnień związanych z wydajnością, zobacz „Uwagi” w dalszej części tego tematu.

Oto cytat z późniejszego artykułu:

Jeśli liczba stron, które mają być opróżnione w jednej partii, przekracza wewnętrzny próg, może wystąpić pełne skanowanie puli buforów w celu zidentyfikowania stron, które mają zostać opróżnione po zatwierdzeniu partii. To pełne skanowanie może zaszkodzić wydajności importu zbiorczego. Prawdopodobny przypadek przekroczenia wewnętrznego progu występuje, gdy duża pula buforów jest połączona z wolnym podsystemem We / Wy. Aby uniknąć przepełnienia bufora na dużych komputerach, nie używaj wskazówki TABLOCK (która usunie optymalizacje zbiorcze) lub użyj mniejszej wielkości partii (która zachowuje optymalizacje zbiorcze).

Ponieważ komputery różnią się, zalecamy przetestowanie różnych wielkości partii przy ładowaniu danych, aby dowiedzieć się, co będzie dla Ciebie najlepsze.

Osobiście po prostu wstawiłbym wszystkie 695 wierszy w jednej partii. Strojenie wielkości partii może jednak mieć duże znaczenie przy wstawianiu dużej ilości danych.

4. Upewnij się, że potrzebujesz IDENTITYkolumny

Nie wiem nic o twoim modelu danych ani wymaganiach, ale nie wpadam w pułapkę dodawania IDENTITYkolumny do każdej tabeli. Aaron Bertrand ma artykuł na ten temat o nazwie Złe nawyki, które należy wykopać: umieszczając kolumnę TOŻSAMOŚCI na każdym stole . Dla jasności nie mówię, że powinieneś usunąć IDENTITYkolumnę z tej tabeli. Jeśli jednak stwierdzisz, że IDENTITYkolumna nie jest konieczna, usuń ją, co może poprawić wydajność wstawiania.

5. Wyłącz indeksy lub ograniczenia

Jeśli ładujesz dużą ilość danych do tabeli w porównaniu z tym, co już masz, może być szybsze wyłączenie indeksów lub ograniczeń przed ładowaniem i włączenie ich po ładowaniu. W przypadku dużych ilości danych zwykle bardziej nieefektywne jest utworzenie przez SQL Server indeksu naraz zamiast wczytywania danych do tabeli. Wygląda na to, że wstawiłeś 695 wierszy do tabeli z 11500 wierszami, więc nie poleciłbym tej techniki.

6. Rozważ TF 610

Flaga śledzenia 610 umożliwia minimalne logowanie w niektórych dodatkowych scenariuszach. W przypadku tabeli z IDENTITYkluczem klastrowym uzyskasz minimalne rejestrowanie dla nowych stron danych, o ile model odzyskiwania jest prosty lub zbiorczo. Uważam, że ta funkcja nie jest domyślnie włączona, ponieważ może obniżyć wydajność w niektórych systemach. Przed włączeniem tej flagi śledzenia należy dokładnie przetestować. Zalecanym odniesieniem Microsoft nadal wydaje się Przewodnik wydajności ładowania danych

Wpływ minimalnego rejestrowania we / wy pod flagą śledzenia 610

Po zatwierdzeniu transakcji ładowania masowego, która została minimalnie zarejestrowana, wszystkie załadowane strony muszą zostać opróżnione na dysk przed zakończeniem zatwierdzenia. Wszelkie opróżnione strony, które nie zostały przechwycone przez wcześniejszą operację punktu kontrolnego, mogą tworzyć wiele przypadkowych operacji we / wy. Porównaj to z w pełni zalogowaną operacją, która zamiast tego tworzy sekwencyjne operacje we / wy w zapisie dziennika i nie wymaga, aby załadowane strony były opróżniane na dysk w czasie zatwierdzania.

Jeśli twoim scenariuszem ładowania są małe operacje wstawiania na drzewach, które nie przekraczają granic punktów kontrolnych, a masz wolny system we / wy, użycie minimalnego rejestrowania może faktycznie spowolnić prędkości wstawiania.

O ile mogę stwierdzić, nie ma to nic wspólnego z flagą śledzenia 610, ale raczej z samym minimalnym logowaniem. Wierzę, że wcześniejszy cytat o ROWS_PER_BATCHtuningu dotyczył tej samej koncepcji.

Podsumowując, prawdopodobnie nie możesz wiele zrobić, aby dostroić swoje BULK INSERT. Nie martwiłbym się liczbą odczytów, którą zaobserwowałeś przy swojej wkładce. SQL Server zgłosi odczyt za każdym razem, gdy wstawisz dane. Rozważ następujące bardzo proste INSERT:

DROP TABLE IF EXISTS X_TABLE;

CREATE TABLE X_TABLE (
VAL VARCHAR(1000) NOT NULL
);

SET STATISTICS IO, TIME ON;

INSERT INTO X_TABLE WITH (TABLOCK)
SELECT REPLICATE('Z', 1000)
FROM dbo.GetNums(10000); -- generate 10000 rows

Wyjście z SET STATISTICS IO, TIME ON:

Tabela „X_TABLE”. Liczba skanów 0, logiczne odczyty 11428

Zgłoszono 11428 odczytów, ale nie jest to informacja możliwa do wykonania. Czasami liczbę zgłaszanych odczytów można zmniejszyć przez minimalne rejestrowanie, ale oczywiście różnicy nie można bezpośrednio przełożyć na wzrost wydajności.

Joe Obbish
źródło
12

Zacznę odpowiadać na to pytanie, z zamiarem ciągłego aktualizowania tej odpowiedzi, gdy buduję bazę wiedzy o sztuczkach. Mam nadzieję, że inni zetkną się z tym i pomogą mi poprawić moją wiedzę w tym procesie.

  1. Gut Check: Czy twoja zapora ogniowa wykonuje stanową, głęboką kontrolę pakietów? W Internecie nie znajdziesz dużo na ten temat, ale jeśli twoje wkładki zbiorcze są około 10 razy wolniejsze niż powinny, być może masz urządzenie zabezpieczające przeprowadzające głęboką kontrolę pakietów poziomu 3-7 i sprawdzające „Ogólne zapobieganie wstrzykiwaniu SQL „.

  2. Zmierz rozmiar danych, które planujesz wstawić zbiorczo, w bajtach, na partię. I sprawdź, czy przechowujesz jakieś dane LOB, ponieważ jest to osobna operacja pobierania i zapisu strony.

    Kilka powodów, dla których powinieneś to zrobić w ten sposób:

    za. W AWS elastyczna blokowa pamięć masowa IOPS jest dzielona na bajty, a nie wiersze.

    1. Zobacz Wydajność woluminów EBS Amazon w instancjach Linux »Charakterystyka I / O i monitorowanie, aby uzyskać wyjaśnienie, czym jest jednostka IOPS EBS
    2. W szczególności woluminy SSD ogólnego zastosowania (gp2) mają koncepcję „kredytów we / wy i wydajności serii” i często ciężkie przetwarzanie ETL wyczerpuje kredyty salda serii. Czas trwania serii jest mierzony w bajtach, a nie w wierszach programu SQL Server :)

    b. Podczas gdy większość bibliotek lub białych dokumentów testuje na podstawie liczby wierszy, tak naprawdę jest to liczba stron, które można zapisać na ten temat, a aby to obliczyć, musisz wiedzieć, ile bajtów na wiersz i rozmiar strony (zwykle 8 KB , ale zawsze sprawdź dwukrotnie, czy system odziedziczył po kimś innym).

    SELECT *
    FROM 
    sys.dm_db_index_physical_stats(DB_ID(),OBJECT_ID(N'YourTable'), NULL, NULL, 'DETAILED')

    Zwróć uwagę na avg_record_size_in_bytes i page_count.

    do. Jak wyjaśnia Paul White w https://sqlperformance.com/2019/05/sql-performance/minimal-logging-insert-select-heap , „Aby włączyć minimalne rejestrowanie za pomocą INSERT...SELECT, SQL Server musi oczekiwać więcej niż 250 wierszy o całkowitym rozmiarze co najmniej jednego zakresu (8 stron). ”

  3. Jeśli masz jakieś indeksy z ograniczeniami sprawdzania lub ograniczeniami unikalnymi, użyj SET STATISTICS IO ONi SET STATISTICS TIME ON(lub SQL Server Profiler lub SQL Server Extended Events) do przechwytywania informacji, takich jak to, czy twoja wstawka zbiorcza ma jakieś operacje odczytu. Operacje odczytu wynikają z mechanizmu bazy danych SQL Server, który upewnia się, że ograniczenia integralności minęły.

  4. Spróbuj utworzyć testową bazę danych, w której PODSTAWAFILEGROUP jest zamontowana na dysku RAM. Powinno to być nieco szybsze niż SSD, ale także wyeliminować wszelkie pytania, czy kontroler RAID może dodawać koszty ogólne. W 2018 r. Nie powinno tak być, ale tworząc wiele różnicowych linii bazowych, takich jak ta, można uzyskać ogólny pomysł na temat tego, ile narzutu dodaje sprzęt.

  5. Umieść także plik źródłowy na dysku RAM.

    Umieszczenie pliku źródłowego na dysku RAM wyklucza wszelkie problemy sporne, jeśli czytasz plik źródłowy z tego samego dysku, na którym działa FILEGROUP serwera bazy danych.

  6. Sprawdź, czy sformatowałeś swój dysk twardy przy użyciu zakresu 64 KB.

  7. Użyj UserBenchmark.com i przetestuj dysk SSD. Spowoduje to:

    1. Dodaj więcej wiedzy innym miłośnikom wydajności na temat oczekiwanej wydajności urządzenia
    2. Pomóż dowiedzieć się, czy wydajność twojego dysku jest słabsza od innych z tym samym napędem
    3. Pomóż dowiedzieć się, czy wydajność twojego dysku jest gorsza od innych dysków z tej samej kategorii (SSD, HDD itp.)
  8. Jeśli wywołujesz „INSERT BULK” z C # za pomocą rozszerzeń Entity Framework, upewnij się, że najpierw „rozgrzałeś” JIT i „wyrzuciłeś” kilka pierwszych wyników.

  9. Spróbuj utworzyć liczniki wydajności dla swojego programu. Dzięki .NET możesz używać benchmark.NET , który automatycznie profiluje kilka podstawowych wskaźników. Następnie możesz udostępnić swoje próby profilowania społeczności open source i sprawdzić, czy osoby korzystające z innego sprzętu zgłaszają te same dane (tj. Z mojego wcześniejszego punktu na temat porównywania UserBenchmark.com).

  10. Spróbuj użyć nazwanych potoków i uruchom go jako localhost.

  11. Jeśli celujesz w SQL Server i używasz .NET Core, rozważ rozkręcenie Linuksa za pomocą SQL Server Std Edition - kosztuje to mniej niż dolara za godzinę, nawet w przypadku poważnego sprzętu. Główną zaletą wypróbowania tego samego kodu na tym samym sprzęcie z innym systemem operacyjnym jest sprawdzenie, czy stos TCP / IP jądra systemu operacyjnego powoduje problemy.

  12. Skorzystaj z zapytań diagnostycznych SQL Server Glen Barry, aby zmierzyć opóźnienie napędu dla dysku przechowującego FILEGROUP tabeli bazy danych.

    za. Pamiętaj, aby zmierzyć przed testem i po teście. „Przed testem” po prostu mówi ci, czy masz okropne cechy IO jako linię bazową.

    b. Do pomiaru „podczas testu” naprawdę musisz użyć liczników wydajności PerfMon.

    Dlaczego? Ponieważ większość serwerów baz danych korzysta z pamięci sieciowej (NAS). W chmurze, w AWS, Elastic Block Storage jest właśnie tym. Możesz być związany przez IOPS swojego rozwiązania wolumenu / NAS EBS.

  13. Użyj jakiegoś narzędzia do pomiaru statystyk oczekiwania. Monitor Red Gate SQL , analizator wydajności bazy danych SolarWinds, a nawet zapytania diagnostyczne SQL Server Glen Barry, lub zapytanie Wait Statistics Paula Randala .

    za. Najczęstszymi typami oczekiwania będą prawdopodobnie Pamięć / Procesor, WRITELOG, PAGEIOLATCH_EX i ASYNC_NETWORK_IO .

    b. Możesz uruchomić dodatkowe typy oczekiwania, jeśli korzystasz z grup dostępności.

  14. Zmierz efekty wielu jednoczesnych INSERT BULKpoleceń przy TABLOCKwyłączonym (TABLOCK prawdopodobnie wymusi serializację poleceń INSERT BULK). Twoje wąskie gardło może czekać na INSERT BULKzakończenie; powinieneś spróbować ustawić w kolejce tyle zadań, ile może obsłużyć fizyczny model danych serwera bazy danych.

  15. Rozważ podzielenie tabeli na partycje. Jako szczególny przykład: jeśli tabela bazy danych zawiera tylko append, Andrew Novick zasugerował utworzenie „DZISIAJ” FILEGROUPi podzielenie go na co najmniej dwie aplikacje, DZIŚ i BEFORE_TODAY. W ten sposób, jeśli twoje INSERT BULKdane są tylko danymi na dziś, możesz filtrować według pola CreatedOn, aby wymusić trafienie wszystkich wstawek w jedno FILEGROUP, a tym samym zmniejszyć blokowanie podczas używania TABLOCK. Technikę tę opisano bardziej szczegółowo w oficjalnym dokumencie Microsoft: Partycjonowane strategie tabel i indeksów przy użyciu programu SQL Server 2008

  16. Jeśli korzystasz z indeksów magazynu kolumn, wyłącz TABLOCKi ładuj dane w 102.400 wierszach Rozmiar partii. Następnie możesz załadować wszystkie dane równolegle bezpośrednio do grup wierszy magazynu kolumn. Ta sugestia (i udokumentowana racjonalność) pochodzi z indeksów Microsoft Columnstore - Wskazówki dotyczące ładowania danych :

    Ładowanie zbiorcze ma następujące wbudowane optymalizacje wydajności:

    Obciążenia równoległe: Możesz mieć wiele współbieżnych obciążeń masowych (bcp lub wstawianie zbiorcze), z których każde ładuje osobny plik danych. W przeciwieństwie do masowych ładowań magazynu wierszy do programu SQL Server, nie trzeba tego określać, TABLOCKponieważ każdy wątek importu zbiorczego ładuje dane wyłącznie do oddzielnych grup wierszy (skompresowane lub delta grup wierszy) z wyłączną blokadą. Użycie TABLOCKspowoduje wymuszenie wyłączności blokady na stole i nie będzie można importować danych równolegle.

    Minimalne logowanie:Obciążenie masowe używa minimalnego logowania danych, które trafiają bezpośrednio do skompresowanych grup wierszy. Wszelkie dane, które trafiają do grupy wierszy delta, są w pełni rejestrowane. Obejmuje to wszelkie wielkości partii, które są mniejsze niż 102 400 wierszy. Jednak przy ładowaniu zbiorczym celem jest, aby większość danych pominęła grupy wierszy delta.

    Optymalizacja blokowania: Podczas ładowania do skompresowanej grupy wierszy nabywana jest blokada X w grupie wierszy. Jednak podczas masowego ładowania do delta rowgroup, blokada X jest uzyskiwana w rowgroup, ale SQL Server nadal blokuje blokady PAGE / EXTENT, ponieważ blokada X rowgroup nie jest częścią hierarchii blokowania.

  17. Począwszy od SQL Server 2016, nie trzeba już włączać flagi śledzenia 610 dla minimalnego logowania do tabeli indeksowanej . Cytując inżyniera Microsoft Parikshita Savjaniego ( moje podkreślenie ):

    Jednym z celów projektowych SQL Server 2016 była poprawa wydajności i skalowalności silnika po wyjęciu z pudełka, aby działał szybciej bez potrzeby używania jakichkolwiek pokręteł ani flag śledzenia dla klientów. W ramach tych ulepszeń jednym z ulepszeń wprowadzonych w kodzie silnika SQL Server było włączenie kontekstu ładowania masowego (zwanego również szybkim wstawianiem lub kontekstem szybkiego ładowania) i domyślnie minimalne rejestrowanie podczas wykonywania operacji ładowania masowego w bazie danych za pomocą prostych lub masowo zalogowany model odzyskiwania. Jeśli nie znasz minimalnego rejestrowania, gorąco polecam przeczytanie tego postu na blogu od Sunil Agrawal, w którym wyjaśnia on, jak minimalne rejestrowanie działa w SQL Server. Aby wkładki masowe były minimalnie rejestrowane, nadal musi spełniać warunki wstępne, które są tutaj udokumentowane.

    W ramach tych ulepszeń w SQL Server 2016 nie trzeba już włączać flagi śledzenia 610 w celu minimalnego logowania do tabeli indeksowaneji dołącza do niektórych innych flag śladowych (1118, 1117, 1236, 8048), aby stać się częścią historii. W programie SQL Server 2016, gdy operacja ładowania zbiorczego powoduje przydzielenie nowej strony, wszystkie wiersze wypełniające sekwencyjnie tę nową stronę są minimalnie rejestrowane, jeśli wszystkie inne warunki wstępne dotyczące minimalnego rejestrowania opisane wcześniej są spełnione. Wiersze wstawione do istniejących stron (bez przydzielania nowych stron) w celu utrzymania kolejności indeksów są nadal w pełni rejestrowane, podobnie jak wiersze, które są przenoszone w wyniku podziału strony podczas ładowania. Ważne jest również włączenie ALLOW_PAGE_LOCKS dla indeksów (które jest domyślnie WŁĄCZONE), aby minimalna operacja rejestrowania działała, ponieważ blokady stron są uzyskiwane podczas alokacji, a tym samym rejestrowane są tylko alokacje strony lub zakresu.

  18. Jeśli używasz SqlBulkCopy w C # lub EntityFramework.Extensions (który używa SqlBulkCopy pod maską), sprawdź konfigurację kompilacji. Czy przeprowadzasz testy w trybie Release? Czy architektura docelowa jest ustawiona na dowolny procesor / x64 / x86?

  19. Rozważ użycie sp_who2, aby sprawdzić, czy transakcja INSERT BULK jest ZAWIESZONA. Może być ZAWIESZONY, ponieważ jest zablokowany przez innego pająka. Zastanów się, jak zminimalizować blokowanie programu SQL Server . Możesz także użyć sp_WhoIsActive Adama Machanica, ale sp_who2 dostarczy ci podstawowych informacji, których potrzebujesz.

  20. Być może masz po prostu zły dysk I / O. Jeśli wykonujesz wkładkę zbiorczą, a wykorzystanie dysku nie osiąga 100% i utknie na poziomie około 2%, prawdopodobnie masz złe oprogramowanie układowe lub wadliwe urządzenie we / wy. (Zdarzyło się to mojemu współpracownikowi.) Użyj [SSD UserBenchmark], aby porównać z innymi pod względem wydajności sprzętowej, szczególnie jeśli możesz odtworzyć powolność na lokalnym komputerze deweloperskim. (To ostatnie umieszczam na liście, ponieważ większość firm nie zezwala programistom na uruchamianie baz danych na komputerze lokalnym ze względu na ryzyko związane z IP).

  21. Jeśli tabela korzysta z kompresji, możesz spróbować uruchomić wiele sesji, a w każdej z nich zacznij od użycia istniejącej transakcji i uruchom ją przed poleceniem SqlBulkCopy:

    ALTER CONFIGURATION SERVER SET PROCESS AFFINITY CPU = AUTO;

  22. W przypadku ciągłego ładowania jeden strumień pomysłów, po raz pierwszy nakreślony w oficjalnym dokumencie Microsoft, strategiach dotyczących tabel partycjonowanych i indeksów przy użyciu programu SQL Server 2008 :

    Ciągłe ładowanie

    W scenariuszu OLTP ciągle pojawiają się nowe dane. Jeśli użytkownicy odpytują również o najnowszą partycję, ciągłe wstawianie danych może prowadzić do blokowania: zapytania użytkowników mogą blokować wstawki, podobnie wstawki mogą blokować zapytania użytkowników.

    Koncentrację na tabeli ładowania lub partycji można zmniejszyć, stosując izolację migawkową - w szczególności READ COMMITTED SNAPSHOTpoziom izolacji. W READ COMMITTED SNAPSHOTizolacji, wstawki do tabeli nie powodują aktywności w magazynie wersji tempdb , więc obciążenie tempdb jest minimalne dla wstawek, ale zapytania udostępnione na tej samej partycji nie będą podejmowane.

    W innych przypadkach, gdy dane są wstawiane do tabeli podzielonej na partycje w sposób ciągły z dużą szybkością, nadal może być możliwe stopniowanie danych przez krótki czas w tabelach pomostowych, a następnie wielokrotne wstawianie tych danych do najnowszej partycji, aż pojawi się okno bieżąca partycja mija, a następnie dane są wstawiane do następnej partycji. Załóżmy na przykład, że masz dwie tabele pomostowe, z których każda otrzymuje dane o wartości 30 sekund na przemian: jedna tabela za pierwszą połowę minuty, druga tabela za drugą połowę minuty. Procedura przechowywana wstawiania określa, w której połowie minuty znajduje się bieżąca wkładka, a następnie wstawia ją do pierwszej tabeli pomostowej. Po upływie 30 sekund procedura wstawiania określa, że ​​należy wstawić do drugiej tabeli pomostowej. Kolejna procedura składowana ładuje następnie dane z pierwszej tabeli pomostowej do najnowszej partycji tabeli, a następnie obcina pierwszą tabelę pomostową. Po kolejnych 30 sekundach ta sama procedura przechowywana wstawia dane z drugiej procedury przechowywanej i umieszcza ją w bieżącej partycji, a następnie obcina drugą tabelę pomostową.

  23. Zespół Microsoft CAT The Performance Load Guide Guide

  24. Upewnij się, że Twoje statystyki są aktualne. Użyj FULLSCAN, jeśli możesz po każdej kompilacji indeksu.

  25. Dostrajanie wydajności sieci SAN za pomocą SQLIO, a także upewnij się, że używasz dysków mechanicznych, że partycje dysków są wyrównane. Zobacz Najważniejsze wskazówki dotyczące wyrównywania partycji dysków firmy Microsoft .

  26. COLUMNSTORE INSERT/ UPDATEperformance

John Zabroski
źródło
2

Odczyty prawdopodobnie będą unikalnymi ograniczeniami i FK sprawdzanymi podczas wstawiania - możesz uzyskać poprawę prędkości, jeśli możesz je wyłączyć / upuścić podczas wstawiania i włączyć / odtworzyć później. Musisz przetestować, czy to ogólnie spowalnia działanie w porównaniu do utrzymywania ich aktywności. Może to również nie być dobrym pomysłem, jeśli inne procesy zapisują jednocześnie do tej samej tabeli. - Gareth Lyons

Zgodnie z pytaniami i pytaniami Klucze obce stają się niezaufane po wstawieniu zbiorczym , ograniczenia FK stają się niezaufane po opcji BULK INSERTbez CHECK_CONSTRAINTSopcji (mój przypadek, gdy zakończyłem z niezaufanymi ograniczeniami). Nie jest jasne, ale nie ma sensu sprawdzać ich i nadal sprawiać, że nie są zaufani. Jednak PK i UNIQUE będą nadal sprawdzane (patrz WIELKIE WSTAWIENIE (Transact-SQL) ). - Aleksiej

użytkownik126897
źródło