Mamy bazę danych dla produktu, który wymaga dużego zapisu. Właśnie kupiliśmy nowy serwer z dyskiem SSD, aby pomóc. Ku naszemu zdziwieniu wstawki nie były szybsze niż na naszej starej maszynie z dużo wolniejszym przechowywaniem. Podczas testów porównawczych zauważyliśmy, że wskaźnik operacji we / wy wykazywany przez proces SQL Server był bardzo niski.
Na przykład uruchomiłem skrypt znaleziony na tej stronie , z tą różnicą, że dodałem BEGIN TRAN i COMMIT wokół pętli. W najlepszym wypadku mogłem zobaczyć, że użycie dysku osiąga 7 Mb / s, a procesor ledwo dotknął 5%. Serwer ma zainstalowaną 64 Gb i używa 10. Całkowity czas działania wyniósł 2 minuty 15 sekund dla pierwszego połączenia i około 1 minuty dla kolejnych połączeń. Baza danych jest na prostym odzyskiwaniu i była bezczynna podczas testu. Upuściłem stolik między każdą rozmową.
Dlaczego tak prosty skrypt jest tak wolny? Sprzęt w ogóle nie jest używany. Zarówno narzędzia do analizy porównawczej dysków, jak i SQLIO wskazują, że dysk SSD działa poprawnie z prędkościami do 500 Mb / s zarówno w przypadku odczytu, jak i zapisu. Rozumiem, że zapisy losowe są wolniejsze niż zapisy sekwencyjne, ale oczekiwałbym, że taka prosta wstawka do tabeli bez indeksowania klastrowego będzie znacznie szybsza.
Ostatecznie nasz scenariusz jest znacznie bardziej złożony, ale uważam, że najpierw muszę zrozumieć prosty przypadek. W skrócie nasza aplikacja usuwa stare dane, a następnie używa SqlBulkCopy do kopiowania nowych danych do tabel pomostowych, wykonuje pewne filtrowanie, a na koniec używa MERGE i / lub INSERT INTO w zależności od przypadków, aby skopiować dane do ostatecznych tabel.
-> EDYCJA 1: Postępowałem zgodnie z procedurą powiązaną przez Martina Smitha i otrzymałem następujący wynik:
[Wait Type] [Wait Count] [Total Wait (ms)] [T. Resource Wait (ms)] [T. Signal Wait (ms)]
NETWORK_IO 5008 46735 46587 148
LOGBUFFER 901 5994 5977 17
PAGELATCH_UP 40 866 865 1
SOS_SCHEDULER_YIELD 53279 219 121 98
WRITELOG 5 145 145 0
PAGEIOLATCH_UP 4 58 58 0
LATCH_SH 5 0 0 0
Uważam, że to dziwne NETWORK_IO zajmuje większość czasu, biorąc pod uwagę, że nie ma żadnych wyników do wyświetlenia i żadnych danych do przesłania gdziekolwiek poza plikami SQL. Czy typ NETWORK_IO obejmuje wszystkie operacje wejścia / wyjścia?
-> EDYCJA 2: Utworzyłem dysk RAM 20 Gb i stamtąd zamontowałem bazę danych. Najlepszy czas, jaki miałem na dysku SSD to 48s, z dyskiem RAM spadł do 37 sekund. NETWORK_IO jest nadal największym oczekiwaniem. Maksymalna prędkość zapisu na dysku RAM wynosiła około 250 Mb / s, podczas gdy jest on w stanie wykonać wiele gigabajtów na sekundę. Nadal nie zużywał dużo procesora, więc co powstrzymuje SQL?
SET NOCOUNT ON
do tego dodał .NETWORK_IO
może być od 3 mln „1 row (s) affected” wiadomości są odsyłane. Czy próbowałeś dodaćSET NOCOUNT ON
do skryptu?EE_WaitStats*.xel
więc stare zepsują twoje wyniki.Odpowiedzi:
Wiem, że to stare pytanie, ale wciąż może pomóc wyszukiwarkom i jest to problem, który pojawia się co jakiś czas.
Głównym powodem, dla którego osiągasz pułap wydajności, nie zauważając wąskiego gardła zasobów, jest to, że osiągnąłeś limit możliwości przetwarzania jednego wątku w ramach jednej sesji. Pętla nie jest przetwarzana równolegle, ale wszystkie wstawki są wykonywane szeregowo.
W moim przypadku wstawienie 3 milionów wierszy zajmuje 36 sekund. Oznacza to 36/30000000 = 0,000012 sekund na rząd. To dość szybko. W moim systemie wystarczy 0,000012, aby przejść wszystkie niezbędne kroki.
Jedynym sposobem, aby to zrobić szybciej, jest rozpoczęcie drugiej sesji równolegle.
Jeśli rozpocznę 2 sesje równolegle, obie zrobią 15 milionów wstawek. Oba kończą w 18 sekund. Mógłbym zwiększyć skalę, ale moja obecna konfiguracja testowa osiąga 95% procesora w dwóch równoległych sesjach, więc wykonanie 3 zmieniłoby wyniki, ponieważ trafiłbym na wąskie gardło procesora.
Jeśli rozpocznę 2 równoległe sesje, oba wstawią 3 miliony wierszy, oba zakończą się w 39 sekund. więc jest to teraz 6 milionów wierszy w 39 sekund.
Okej, to wciąż pozostawia nam pojawienie się NETWORK_IO.
Oczekiwania NETWORK_IO są dodawane przez fakt, że do ich śledzenia używasz zdarzeń rozszerzonych. W moim przypadku wstawka zajmuje 36 sekund (średnio). Podczas korzystania z metody rozszerzonego zdarzenia (z linku powyżej w pierwszym komentarzu) rejestruje się:
Widać, że 68 sekund NETWORK_IO jest zarejestrowanych. Ale ponieważ pętla wstawiania jest pojedynczym wątkiem, który zajął 36 sekund, nie może tak być. (Tak, używanych jest wiele wątków, ale operacje są szeregowe, nigdy równoległe, więc nie można skumulować więcej czasu oczekiwania niż całkowity czas trwania zapytania)
Jeśli nie używam zdarzeń rozszerzonych, a tylko statystyki DMV czekania w cichym wystąpieniu (tylko z uruchomioną wstawką), otrzymuję to:
NETWORK_IO, które widziałeś w rozszerzonym dzienniku zdarzeń, nie było związane z twoją pętlą wstawiania. (Gdybyś nie włączył nocount, miałbyś masową asynchroniczną sieć IO czeka, +1 Martin)
Jednak nie wiem, dlaczego NETWORK_IO pojawia się w rozszerzonym śledzeniu zdarzeń. Upewnij się, że zapisywanie w celu pliku asynchronicznego zdarzeń gromadzi ASYNC_NETWORK_IO, ale na pewno wszystko to odbywa się na innym SPID niż ten, na którym filtrujemy. Mogę zadać to jako nowe pytanie)
źródło
Zazwyczaj można rozpocząć patrząc
sys.dm_exec_requests
, szczególnie uwait_time
,wait_type
await_resource
na życzenie wkładka (ów). To da wyraźne wskazanie, co blokuje WSTAW. Wyniki wskażą, czy jest to rywalizacja o blokadę, zdarzenia wzrostu plików, oczekiwanie na opróżnienie dziennika, rywalizacja o alokację (manifestuje się jako rywalizacja o zatrzask strony PFS) itp. Itd. Po zmierzeniu odpowiednio zaktualizuj swoje pytanie. Gorąco zachęcam do zatrzymania się teraz i zapoznania się z metodologią rozwiązywania problemów z kolejkami i kolejkami przed kontynuowaniem.źródło
Uruchomiłem skrypt testowy na stronie połączonej w OP z BEGIN TRAN / COMMIT wokół pętli. Na moim komputerze ukończenie pierwszego razu zajęło 1:28.
Następnie przeniosłem te dwa polecenia poza pętlę:
Ukończono po 28 sekundach.
Nie wiem na pewno, co się dzieje, ale domyślam się, że w
RAND()
kodzie może być jakiś sen , być może jako część algorytmu, którego używają do generowania entropii (lepszych liczb losowych).FWIW, dyski SSD nie zawsze są najlepszą technologią dla aplikacji wymagających dużego zapisu. Aby uzyskać najlepszą wydajność, upewnij się, że dziennik DB znajduje się na innej literze dysku niż dane DB, plik dziennika jest wstępnie powiększony do maksymalnego rozmiaru i nigdy nie obcinaj dziennika.
źródło
Innym DMV, którego używam do identyfikowania powolności, jest sys.dm_os_waiting_tasks . Jeśli twoje zapytanie nie wymaga dużego procesora, możesz znaleźć więcej informacji na temat oczekiwań z tego DMV.
źródło
Sprawdzam listę zdarzeń oczekiwania dla SQL 2008 i nie widzę na liście NETWORK_IO: http://technet.microsoft.com/en-us/library/ms179984(v=sql.100).aspx
Myślałem, że NETWORK_IO jest teraz na liście ASYNC_NETWORK_IO, więc chciałem zapytać, czy możesz ponownie sprawdzić swoją wersję SQL, ponieważ jestem po prostu ciekawy, jak / dlaczego to zdarzenie oczekiwania pojawia się dla tej wersji.
Jeśli chodzi o pojawienie się sieci, tak, może się to zdarzyć, nawet jeśli pracujesz na samodzielnym serwerze. Czy sprawdziłeś ustawienia swoich kart sieciowych? Zastanawiam się, czy to problem.
Na koniec dnia możliwe jest tylko kilka wąskich gardeł zasobów: pamięć, procesor, dyskowe operacje we / wy, sieć i blokowanie. Wskazałeś, że nie ma problemu z CPU i I / O, i masz zdarzenie oczekiwania NETWORK_IO, więc sugeruję, abyś najpierw spojrzał na te karty sieciowe.
źródło
NETWORK_IO
Pokazano ponieważ OP używa rozszerzonych zdarzeń. Nigdy nie został zaktualizowany wsys.dm_xe_map_values