Mamy dużą bazę danych, około 1 TB, działającą na serwerze SQL Server 2014 na silnym serwerze. Wszystko działało dobrze przez kilka lat. Około 2 tygodnie temu wykonaliśmy pełną konserwację, która obejmowała: Zainstalowanie wszystkich aktualizacji oprogramowania; odbuduj wszystkie indeksy i kompaktowe pliki DB. Nie spodziewaliśmy się jednak, że na pewnym etapie wykorzystanie procesora przez DB wzrosło o ponad 100% do 150%, gdy rzeczywiste obciążenie było takie samo.
Po wielu problemach rozwinęliśmy to do bardzo prostego zapytania, ale nie mogliśmy znaleźć rozwiązania. Zapytanie jest niezwykle proste:
select top 1 EventID from EventLog with (nolock) order by EventID
To zawsze zajmuje około 1,5 sekundy! Jednak podobne zapytanie z „desc” zawsze zajmuje około 0 ms:
select top 1 EventID from EventLog with (nolock) order by EventID desc
PTable ma około 500 milionów wierszy; EventID
to podstawowa kolumna indeksu klastrowego (uporządkowana ASC
) z typem danych bigint (kolumna Tożsamość). Istnieje wiele wątków wstawiających dane do tabeli u góry (większe Identyfikatory zdarzeń), a 1 wątek usuwa dane z dołu (mniejsze Identyfikatory zdarzeń).
W SMSS zweryfikowaliśmy, że dwa zapytania zawsze używają tego samego planu wykonania:
Skanowanie indeksu klastrowego;
Szacowane i rzeczywiste numery wierszy wynoszą 1;
Szacowana i faktyczna liczba egzekucji wynosi 1;
Szacunkowy koszt we / wy wynosi 8500 (wydaje się, że jest wysoki)
Jeśli uruchamiane są kolejno, koszt zapytania jest taki sam 50% dla obu.
Zaktualizowałem statystyki indeksu with fullscan
, problem nadal występował; Zbudowałem indeks ponownie i problem zniknął na pół dnia, ale wrócił.
Włączyłem statystyki IO z:
set statistics io on
następnie uruchomił dwa zapytania kolejno i znalazł następujące informacje:
(W przypadku pierwszego zapytania, wolne)
Tabela „PTable”. Liczba skanów 1, logiczne odczyty 407670, fizyczne odczyty 0, odczytywanie z wyprzedzeniem 0, lob logiczne odczyty 0, lob fizyczne odczyty 0, lob odczyty 0.
(W przypadku drugiego zapytania, szybkie)
Tabela „PTable”. Liczba skanów 1, logiczne odczyty 4, fizyczne odczyty 0, odczyt z wyprzedzeniem 0, lob logiczne odczyty 0, lob fizyczne odczyty 0, lob odczyty z wyprzedzeniem 0.
Zwróć uwagę na ogromną różnicę w logicznych odczytach. Indeks jest używany w obu przypadkach.
Fragmentacja indeksu może trochę wyjaśnić, ale uważam, że wpływ jest bardzo niewielki; i problem nigdy wcześniej się nie zdarzył. Innym dowodem jest, jeśli uruchomię zapytanie takie jak:
select * from EventLog with (nolock) where EventID=xxxx
Nawet jeśli ustawię xxxx na najmniejsze Identyfikatory zdarzeń w tabeli, zapytanie zawsze jest błyskawiczne.
Sprawdziliśmy i nie ma problemu z blokowaniem / blokowaniem.
Uwaga: Właśnie próbowałem uprościć powyższy problem. „PTable” to tak naprawdę „EventLog”; PID
jest EventID
.
Otrzymuję ten sam wynik testu bez NOLOCK
podpowiedzi.
Czy ktoś może pomóc?
Bardziej szczegółowe plany wykonania zapytań w XML w następujący sposób:
https://www.brentozar.com/pastetheplan/?id=SJ3eiVnob
https://www.brentozar.com/pastetheplan/?id=r1rOjVhoZ
Nie wydaje mi się, że to ważne, aby podać instrukcję tworzenia tabeli. Jest to stara baza danych i działała idealnie dobrze od dłuższego czasu do czasu konserwacji. Sami przeprowadziliśmy wiele badań i zawęziliśmy je do informacji zawartych w moim pytaniu.
Tabela została utworzona normalnie z EventID
kolumną jako kluczem podstawowym, który jest identity
kolumną typu bigint
. W tej chwili wydaje mi się, że problemem jest fragmentacja indeksu. Wydawało się, że zaraz po odbudowaniu indeksu problem zniknął na pół dnia; ale dlaczego wrócił tak szybko ...?