Jak mogę wyeliminować operatora wyszukiwania kluczowego (klastrowanego) w moim planie wykonania?
Tabela tblQuotes
ma już indeks klastrowany (włączony QuoteID
) i 27 indeksów nieklastrowanych, więc staram się już nie tworzyć.
W QuoteID
zapytaniu umieściłem kolumnę indeksu klastrowego , mając nadzieję, że to pomoże - ale niestety nadal tak samo.
Lub zobacz:
Oto, co mówi operator Key Lookup:
Pytanie:
declare
@EffDateFrom datetime ='2017-02-01',
@EffDateTo datetime ='2017-08-28'
SET NOCOUNT ON
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
IF OBJECT_ID('tempdb..#Data') IS NOT NULL
DROP TABLE #Data
CREATE TABLE #Data
(
QuoteID int NOT NULL, --clustered index
[EffectiveDate] [datetime] NULL, --not indexed
[Submitted] [int] NULL,
[Quoted] [int] NULL,
[Bound] [int] NULL,
[Exonerated] [int] NULL,
[ProducerLocationId] [int] NULL,
[ProducerName] [varchar](300) NULL,
[BusinessType] [varchar](50) NULL,
[DisplayStatus] [varchar](50) NULL,
[Agent] [varchar] (50) NULL,
[ProducerContactGuid] uniqueidentifier NULL
)
INSERT INTO #Data
SELECT
tblQuotes.QuoteID,
tblQuotes.EffectiveDate,
CASE WHEN lstQuoteStatus.QuoteStatusID >= 1 THEN 1 ELSE 0 END AS Submitted,
CASE WHEN lstQuoteStatus.QuoteStatusID = 2 or lstQuoteStatus.QuoteStatusID = 3 or lstQuoteStatus.QuoteStatusID = 202 THEN 1 ELSE 0 END AS Quoted,
CASE WHEN lstQuoteStatus.Bound = 1 THEN 1 ELSE 0 END AS Bound,
CASE WHEN lstQuoteStatus.QuoteStatusID = 3 THEN 1 ELSE 0 END AS Exonareted,
tblQuotes.ProducerLocationID,
P.Name + ' / '+ P.City as [ProducerName],
CASE WHEN tblQuotes.PolicyTypeID = 1 THEN 'New Business'
WHEN tblQuotes.PolicyTypeID = 3 THEN 'Rewrite'
END AS BusinessType,
tblQuotes.DisplayStatus,
tblProducerContacts.FName +' '+ tblProducerContacts.LName as Agent,
tblProducerContacts.ProducerContactGUID
FROM tblQuotes
INNER JOIN lstQuoteStatus
on tblQuotes.QuoteStatusID=lstQuoteStatus.QuoteStatusID
INNER JOIN tblProducerLocations P
On P.ProducerLocationID=tblQuotes.ProducerLocationID
INNER JOIN tblProducerContacts
ON dbo.tblQuotes.ProducerContactGuid = tblProducerContacts.ProducerContactGUID
WHERE DATEDIFF(D,@EffDateFrom,tblQuotes.EffectiveDate)>=0 AND DATEDIFF(D, @EffDateTo, tblQuotes.EffectiveDate) <=0
AND dbo.tblQuotes.LineGUID = '6E00868B-FFC3-4CA0-876F-CC258F1ED22D'--Surety
AND tblQuotes.OriginalQuoteGUID is null
select * from #Data
Plan wykonania:
Odpowiedzi:
Kluczowe wyszukiwania różnych odmian występują, gdy procesor zapytań musi uzyskać wartości z kolumn, które nie są przechowywane w indeksie używanym do zlokalizowania wierszy wymaganych do zapytania w celu zwrócenia wyników.
Weźmy na przykład następujący kod, w którym tworzymy tabelę z jednym indeksem:
Wstawimy 1 000 000 wierszy do tabeli, abyśmy mieli pewne dane do pracy:
Teraz przeszukamy dane z opcją wyświetlenia „rzeczywistego” planu wykonania:
Plan zapytań pokazuje:
Zapytanie sprawdza
IX_Table1
indeks, aby znaleźć wiersz,Table1ID = 5000000
ponieważ przeglądanie tego indeksu jest znacznie szybsze niż skanowanie całej tabeli w poszukiwaniu tej wartości. Aby jednak spełnić wyniki zapytania, procesor zapytań musi również znaleźć wartość dla innych kolumn w tabeli; w tym miejscu pojawia się „RID Lookup”. W tabeli szuka identyfikatora wiersza (RID w RID Lookup) powiązanego z wierszem zawierającymTable1ID
wartość 500000, uzyskując wartości zTable1Data
kolumny. Jeśli najedziesz myszką na węzeł „Wyszukiwanie RID” w planie, zobaczysz to:„Lista wyjściowa” zawiera kolumny zwrócone przez wyszukiwanie RID.
Ciekawym przykładem jest tabela z indeksem klastrowanym i indeksem nieklastrowanym. Poniższa tabela ma trzy kolumny; ID, które jest kluczowym klasteryzacji,
Dat
która jest indeksowana nieklastrowanych indeksuIX_Table
i trzeciej kolumnieOth
.Weź przykładowe zapytanie:
Prosimy SQL Server o zwrócenie każdej kolumny z tabeli, w której
Dat
kolumna zawiera słowoTest
. Mamy tutaj kilka możliwości do wyboru; możemy spojrzeć na tabelę (tj. indeks klastrowany) - ale wymagałoby to skanowania całej rzeczy, ponieważ tabela jest uporządkowana wedługID
kolumny, co nie mówi nam nic o tym, które wiersze (wiersze) zawierająTest
wDat
kolumnie. Druga opcja (i ta wybrana przez SQL Server) polega na przeszukiwaniuIX_Table1
indeksu nieklastrowanego w celu znalezienia wiersza, w którymDat = 'Test'
jednak potrzebna jest równieżOth
kolumna, SQL Server musi przeprowadzić wyszukiwanie w indeksie klastrowym za pomocą klucza „ Wyszukiwanie ”. Oto plan:Jeśli będziemy modyfikować indeks nieklastrowanym tak, że zawiera w
Oth
kolumnie:Następnie ponownie uruchom zapytanie:
Widzimy teraz pojedyncze wyszukiwanie indeksu nieklastrowego, ponieważ SQL Server musi po prostu zlokalizować wiersz
Dat = 'Test'
wIX_Table1
indeksie, który zawiera wartośćOth
i wartośćID
kolumny (klucz podstawowy), która jest automatycznie obecna w każdym non-non indeks klastrowy. Plan:źródło
Wyszukiwanie klucza jest spowodowane, ponieważ silnik wybrał indeks, który nie zawiera wszystkich kolumn, które próbujesz pobrać. Tak więc indeks nie obejmuje kolumn w instrukcji select i where.
Aby wyeliminować wyszukiwanie klucza, musisz dołączyć brakujące kolumny (kolumny na liście wyników wyszukiwania klucza) = ProducerContactGuid, QuoteStatusID, PolicyTypeID i ProducerLocationID lub innym sposobem jest wymuszenie użycia zapytania zamiast indeksu klastrowanego.
Należy zauważyć, że 27 indeksów nieklastrowanych w tabeli może mieć negatywny wpływ na wydajność. Podczas uruchamiania aktualizacji, wstawiania lub usuwania SQL Server musi zaktualizować wszystkie indeksy. Ta dodatkowa praca może negatywnie wpłynąć na wydajność.
źródło
Zapomniałeś wspomnieć o ilości danych zaangażowanych w to zapytanie. Również dlaczego wstawiasz do tabeli tymczasowej? Jeśli tylko musisz wyświetlić, nie uruchamiaj instrukcji insert.
Na potrzeby tego zapytania
tblQuotes
nie potrzebuje 27 indeksów nieklastrowych. Potrzebuje 1 indeksu klastrowego i 5 indeksów nieklastrowych lub 6 indeksów nieklastrowych.To zapytanie wymaga indeksów w tych kolumnach:
Zauważyłem również następujący kod:
oznacza
NON Sargable
to, że nie może korzystać z indeksów.Aby ten kod
SARgable
zmienić na następujący:Aby odpowiedzieć na główne pytanie: „dlaczego otrzymujesz klucz Wyszukaj”:
Dostajesz,
KEY Look up
ponieważ część kolumny, która jest wymieniona w zapytaniu, nie występuje w indeksie obejmującym.Możesz google i uczyć się o
Covering Index
lubInclude index
.W moim przykładzie załóżmy, że tblQuotes.QuoteStatusID jest indeksem nieklastrowanym, a następnie mogę również objąć DisplayStatus. Ponieważ chcesz DisplayStatus w zestawie wyników. Dowolną kolumnę, która nie jest obecna w indeksie i jest obecna w zestawie wyników, można zakryć, aby tego uniknąć
KEY Look Up or Bookmark lookup
. Oto przykład obejmujący indeks:** Zastrzeżenie: ** Pamiętaj, że powyżej jest tylko mój przykład DisplayStatus może być objęty innym Non CI po analizie.
Podobnie będziesz musiał utworzyć indeks i indeks obejmujący inne tabele biorące udział w zapytaniu.
Dostajesz się
Index SCAN
także do swojego planu.Może się to zdarzyć, ponieważ w tabeli nie ma indeksu lub gdy jest duża ilość danych, optymalizator może zdecydować się na skanowanie zamiast przeszukiwania indeksu.
Może to również wystąpić z powodu
High cardinality
. Uzyskanie większej liczby rzędów niż jest to wymagane z powodu wadliwego łączenia. Można to również poprawić.źródło