Czy istnieje sposób ustalenia, czy zapytania programu SQL Server są uruchamiane w pamięci, czy na dysku?

13

Dzisiaj spotkałem zestaw procedur przechowywanych w aplikacji, które są wywoływane wielokrotnie w ramach długotrwałego procesu. W ramach każdej procedury znalazłem wiele różnych instrukcji select, niektóre w obrębie pętli; nic dziwnego, że obecnie stosowane procedury zajmują kilka minut, a intuicja spodziewałaby się ich wykonania w ciągu kilku sekund.

Wydaje się dość oczywiste, że wydajność nie była brana pod uwagę przy pisaniu tych procedur, istnieje wiele przypadków rzeczy, które są po prostu „nie dobrym pomysłem”.

Przetwarzanie każdego wiersza podczas importowania danych zajmuje 300 ms na wiersz, więc przetworzenie stosunkowo małego importu zajmuje kilka minut.

Jednak tabele stosowane w procedurach są w większości dość małe. Myślę, że jeśli wszystkie te tabele są w pełni przechowywane w pamięci, być może nie wszystko, co można uzyskać, przepisując cokolwiek z tego.

Próbuję ustalić ... dla tego oczywiście nieefektywnego kodu, jaki to ma prawdziwy wpływ? Czy warto to naprawić?

Pytanie brzmi zatem:
- czy istnieje sposób na określenie, które tabele są całkowicie przypięte do pamięci?
- czy istnieje sposób włączenia śledzenia w celu monitorowania zagnieżdżonych procedur przechowywanych w celu znalezienia szczególnie drogich części?

Uwaga: dotyczy SQL Server 2008 R2

tbone
źródło

Odpowiedzi:

12

Możesz użyć jednego z tych dwóch zapytań, aby zobaczyć całkowitą liczbę odczytów logicznych i całkowitą liczbę odczytów fizycznych.

SELECT  DB_NAME(st.dbid) Db,
        OBJECT_NAME(st.objectid, st.dbid) Prc,
        qs.execution_count,
        qs.total_logical_reads,
        qs.total_physical_reads,
        qs.statement_start_offset,
        qs.statement_end_offset,
        st.text
FROM    sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st;

SELECT  DB_NAME(database_id) Db,
        OBJECT_NAME(object_id, database_id) Prc,
        execution_count,
        total_logical_reads,
        total_physical_reads
FROM    sys.dm_exec_procedure_stats ps;

Pierwszy rozkłada to według instrukcji, drugi liczy się w całej procedurze.

Odczyty fizyczne są odczytywane względem dysku, odczyty logiczne są przeciw pamięci. Możesz użyć tego, aby dowiedzieć się, które procedury lub instrukcje są najdroższe w twoim systemie i spróbować je dostroić.

Należy pamiętać, że chociaż odczyty logiczne są znacznie tańsze niż odczyty fizyczne, wciąż są drogie, więc zmniejszenie ich liczby (na przykład poprzez dodanie odpowiedniego indeksu) może znacznie przyspieszyć zapytania.

Istnieje wiele dodatkowych kolumn w powyższych DMV, które również mogą Cię zainteresować.


W jaki sposób indeks pomaga zredukować logiczne odczyty?

W SQL Server wszystkie dane są zorganizowane w bloki o wielkości 8 KB. Te bloki nazywane są „stronami”.

Każda tabela zawiera strony „meta”, które zawierają informacje o strukturach tabeli, a także strony pata. Jeśli nie istnieje indeks i uruchomisz zapytanie, takie jak SELECT * FROM tbl WHERE Id = 7SQL Server musi szukać tego lub tych wierszy w całej tabeli. Czyta więc po jednej stronie na raz, zapętla wszystkie wiersze na każdej stronie, aby ustalić, które wiersze pasują do WHEREklauzuli. Jeśli więc tabela wymaga przechowywania 1 000 000 stron, to zapytanie wykona 1 000 000 logicznych odczytów.

Jeśli masz indeks, SQL Server sortuje dane logicznie na stronach i ustanawia połączoną listę między stronami. Pozwala to na uruchamianie zapytań ORDER BYdo wykonania bez kosztownej operacji sortowania. Ale co ważne, podczas sortowania SQL Server dodaje drzewo B + do tabeli. Drzewo B + to struktura porównywalna z indeksem w książce, w której wyszukiwanie określonego słowa kluczowego pozwala mi bezpośrednio przejść do strony zawierającej słowo kluczowe. Typowa książka ma tylko jeden poziom indeksu, podczas gdy drzewo B + może mieć wiele. Pomyśl tylko o dużej książce, w której sam indeks ma wiele stron. W takim przypadku ma sens dodanie dodatkowej warstwy indeksu, która mówi nam, na której stronie Smożna znaleźć słowa indeksu zaczynające się.

Drzewa B + są zoptymalizowane pod kątem jak najmniejszej liczby poziomów, zapewniając jednocześnie właściwość, że dowolny rekord w indeksie można znaleźć, czytając jedną stronę na poziom indeksu. Więc załóż powyższe WHERE Id = 7zapytanie, gdy masz posortowany indeks Id. Powiedzmy, że indeks ma 5 poziomów. Teraz, aby znaleźć wszystkie rekordy pasujące do tego zapytania, muszę przeczytać jedną stronę na poziom indeksu (czyli 5 stron). Nazywa się to „Wyszukiwanie indeksu”. Jeśli istnieje wiele rekordów pasujących do rachunku, być może będę musiał przez jakiś czas śledzić posortowany indeks, aby odzyskać wszystkie. Załóżmy jednak, że jest tylko jeden rekord.

Tak więc bez uruchamiania indeksu to zapytanie wymagało 1 000 000 odczytów, a indes wymagało 5 odczytów. Mimo że odczyt logiczny jest operacją w pamięci, nadal istnieje znaczny koszt - w rzeczywistości jest to najdroższa operacja w tak trywialnym zapytaniu, jak powyższe. Zatem zmniejszenie liczby logicznych odczytów wymaganych o współczynnik 200 000 przyspieszy zapytanie o podobny współczynnik.

Czytanie logiczne nie jest więc równoważne skanowaniu tabeli, ale skanowanie tabeli powoduje o wiele więcej logicznych odczytów niż wyszukiwanie indeksu.

Sebastian Meine
źródło
> „... zmniejszenie ich liczby (na przykład poprzez dodanie odpowiedniego indeksu) może znacznie przyspieszyć zapytania.” Czy możesz wyjaśnić, w jaki sposób dodanie indeksu zmniejszy (?) Logiczne odczyty? Czy odczyt logiczny jest synonimem skanowania tabeli?
1
Dodałem wyjaśnienie do mojej powyższej odpowiedzi.
Sebastian Meine
Dzięki. Nawet zakładając, że właściwe tabele znajdują się na wszystkich zaangażowanych tabelach ... Myślę, że nadal istnieje ogromna różnica w wydajności między tabelą przypiętą do pamięci a odczytaną z dysku (załóżmy te same indeksy w obu scenariuszach) ... lub w innych słowami, dodanie indeksów spowoduje mniejszy wzrost wydajności na komputerze z dużą ilością pamięci RAM niż na komputerze z mniejszą pamięcią ... prawda?
1
fizyczny dostęp do dysku jest wyraźnie o rząd wielkości droższy niż dostęp do pamięci. Tak więc podjęcie środków, aby tego uniknąć, zaprowadzi cię bardzo daleko. Nadal powinieneś spojrzeć najpierw na liczbę odczytów logicznych podczas dostrajania zapytań. Utrzymywanie ich na niskim poziomie z kolei utrzyma fizyczne odczyty na niskim poziomie. Istnieje również duża szansa, że ​​strony nie muszą zostać eksmitowane z pamięci podręcznej, co jeszcze bardziej zmniejsza wymagane fizyczne odczyty.
Sebastian Meine
2
Drobny nitpick - Myślę, że strony mają rozmiar 8 KB :-). Dobra odpowiedź.
onupdatecascade
3
  • Czy istnieje sposób włączenia śledzenia w celu monitorowania zagnieżdżonych procedur przechowywanych w celu znalezienia szczególnie drogich części?

Możesz użyć SQL Profiler. Po rozpoczęciu śledzenia należy wybrać RPC Completed, SP Start, SP StmtStarting i SP StmtCompleted (patrz zdjęcie poniżej)

wprowadź opis zdjęcia tutaj

Dzięki temu zobaczysz każde zapytanie uruchamiane w procedurach przechowywanych. Pozwoli ci zobaczyć, ile razy wywoływana jest zagnieżdżona procedura składowana. Po zakończeniu śledzenia należy go zapisać. Następnie otwórz go ponownie, a następnie będziesz mógł filtrować (za pomocą przycisku „Filtry kolumn”), aby znaleźć zapytania, które powodują problem. (np. zapytania, które zajęły więcej niż x odczytów lub które trwały dłużej niż x sekund (czas trwania) ...)

Opcje profilera, które pokazałem, pokazują również plan wykonania, który również jest bardzo pomocny.

Danielle Paquette-Harvey
źródło
1

Wydaje się, że jest to ogólne pytanie dotyczące optymalizacji zapytania. Z twojego opisu:

  1. Spójrz na kod, aby zobaczyć, czy wykonuje przetwarzanie wiersz po rzędzie. Jeśli tak, to często można dokonać rzędów poprawy wielkości, wdrażając tę ​​samą logikę przy użyciu zestawów (przetwarzanych jednocześnie wiele wierszy). Innymi słowy, jeśli działa jak „zapętlić każdy wiersz”, zmień go na „przetwarzaj wszystkie wiersze”. SQL wyróżnia się tym, ponieważ optymalizator może wybierać spośród większej liczby możliwych metod, potencjalnie wykorzystywać równoległość, usuwać wiele narzutów, które pochodzą z jednego rzędu na raz.
  2. Następnie upewnij się, że istnieją indeksy, które wspierają pracę. Często znowu można uzyskać rząd wielkości poprawy z poprawnymi wskaźnikami vs. Dotyczy to pamięci i dostępu do dysku. Procesy mogą nadal zajmować wiele godzin w pamięci RAM, jeśli nie ma odpowiednich indeksów w dużym zestawie danych.
  3. Następnie, mając ustawioną logikę i indeksy, sprawdziłbym, czy strony danych, których dotyczy problem, mieszczą się w pamięci. W tym momencie, jeśli nadal jest duży dostęp do dysku, sensowne jest patrzenie na fizyczne odczyty i aktywność dysku, ponieważ wszystkie duże korzyści z optymalizacji są osiągane w pierwszych dwóch krokach.
onupdatecascade
źródło