9

możliwym wytłumaczeniem jest tu in the commentOptymalizacja SQL Server Query - Nieoczekiwany powolność w prosty zapytania

W SQL Server 2014 Enterprise Edition (64-bit) - Staram się czytać z widoku. Standardowe zapytanie zawiera tylko taką klauzulę: ORDER BY i OFFSET-FETCH.

Metoda 1

SELECT 

    * 

FROM Metadata 
ORDER BY 
    AgeInHours  ASC, 
    RankingPoint DESC, 
    PublishDate  DESC 
OFFSET 150000 ROWS 
FETCH NEXT 40 ROWS ONLY 

to jednak dość proste zapytanie wykonuje prawie 9 razy wolniej (zauważalne przy pomijaniu dużą liczbę rzędów jak 150k) niż w następnym zapytania, który zwraca się ten sam rezultat.

W tym przypadku Czytam klucz podstawowy, a następnie przy użyciu tego jako parametr WHERE...IN funkcji

Podejście 2

SELECT 
    * 
FROM Metadata 
WHERE NewsId IN (
    SELECT 

     NewsId 

    FROM Metadata 
    ORDER BY 
     AgeInHours  ASC, 
     RankingPoint DESC, 
     PublishDate  DESC 
    OFFSET 150000 ROWS 
    FETCH NEXT 40 ROWS ONLY 
) 
ORDER BY 
    AgeInHours  ASC, 
    RankingPoint DESC, 
    PublishDate  DESC 

Bench oznakowanie tych dwóch pokazów ta różnica

(40 row(s) affected) 

SQL Server Execution Times: 
    CPU time = 14748 ms, elapsed time = 3329 ms. 

(40 row(s) affected) 

SQL Server Execution Times: 
    CPU time = 3828 ms, elapsed time = 469 ms. 

Mam indeksy na klucz podstawowy, PubilshDate i ich fragmentat jon jest bardzo niski. Próbowałem również uruchomić podobne kwerendy w stosunku do tabela bazy danych, ale w każdym przypadku drugie podejście daje duże zyski wydajności. Przetestowałem to również na serwerze SQL 2012.

Czy ktoś może wyjaśnić, co się dzieje?

Schemat

Schema

Sposób 1: plan wykonania

Approach 1: Execution Plan

Sposób 2: plan wykonania (lewa część)

Approach 2: Execution Plan (Left part)

Podejście 2: Plan realizacji (z prawej strony)

Approach 2: Execution Plan (Right part)

+0

Jeśli uruchomisz pierwsze podejście i zaznaczysz tylko ** kolumnę "ID", co się stanie? Podejrzewam, że gwiazdka '*' spowalnia zapytanie, ponieważ zmusza do skanowania wszystkich kolumn. – sagi

+0

O wiele szybciej (prawie 9 razy, powiedzmy), jak sądzę, szuka tylko indeksowanej kolumny ("Id"). Zaskakujące jest to, że w drugim zapytaniu nadal czyta się tę samą ilość danych, gdy użyłem klauzuli "WHERE-IN" - ale nie zajmuje to czasu. Co się dzieje za kulisami? – undefined

+3

Czy można uwzględnić plany kwerend i schemat tabeli? –

Odpowiedz

0

Po wykonaniu kwerendy silnik patrzeć na indeksie, które mogłyby być wykorzystane w celu uzyskania najlepszej wydajności . Twoje podejście 1 używa indeksu, który nie zawiera wszystkich kolumn w instrukcji SELECT, co powoduje wyszukiwanie klucza w planie kwerend, w moim doświadczeniu zawsze uzyskuje się niższą wydajność, która używa tylko indeksowanych kolumn w instrukcji SELECT.

Możesz zobaczyć różnicę, jeśli utworzysz indeks dla AgeInHours, RankingPoint, PublishDate i ZAWIERAJ wszystkie kolumny (zalecane tylko do testowania).

Dla twojego drugiego podejścia możesz nawet uzyskać lepszą wydajność, jeśli użyjesz CTE, a następnie wykonasz JOIN zamiast WHERE z IN lub tabelą tymczasową z indeksem, jeśli masz miliony wierszy.

1

W przypadku zapytań o różnych strukturach z tym samym zestawem wyników uzyskuje się różne plany zapytania z różnymi kosztami podejścia i zapytań. Jest to powszechne w przypadku różnych implementacji SQL RDBMS.

Zasadniczo w powyższym przykładzie przy wybieraniu niewielkiej części danych z dużej tabeli należy najpierw zastosować odpowiednią metodę, aby zmniejszyć i zmniejszyć liczbę wierszy w wynikach, a następnie wybrać pełne wiersze ze wszystkimi kolumnami, podobnie jak w przypadku 2. zapytania.

Innym podejściem jest zbudowanie dokładnego indeksu w celu zmniejszenia wyniku w pierwszym kroku. W powyższym pytaniu prawdopodobnie kolumny z klauzuli ORDER BY w tej samej kolumnie i porządku sortowania mogą być rozwiązaniem.

(Nie wysłane strukturę indeksów wymienionych w planach zapytania mogę tylko sobie wyobrazić, co kryje się za ich nazw).

Można również użyć indeksu SQL sugerując kierować SQL optymalizator konkretnego indeksu które uznają najlepiej jak dla zadania, w przypadku, gdy optymalizator SQL nie spełnia swojej roli.