2011-11-29 19 views
7
SELECT X.ID, X.Field4 
FROM 
     #TaxInvoiceData T 
INNER JOIN 
     xxx X 
     ON T.Id = X.Id 
     AND Field2 = @VAR  
     AND Field3 = 'S' 

Kiedy uruchomić kwerendę pełną tabelę skanowania w tabeli X. Nie rozumiem dlaczego, bo klucz podstawowy tabeli X jestDlaczego wykonywane jest skanowanie tabeli?

ID INT ASC 
Field3 CHAR(2) ASC 
Field2 DATETIME ASC Unique Non-clustered 

Istnieje również indeks

Field2 DATETIME ASC Non-Unique Non-clustered 

robi tylko

SELECT ID 
FROM xxx 
WHERE 
    Field2 = @VAR 
AND Field3 = 'S' 

Czy Indeksem Szukajcie

Z góry dziękuję.

+0

Ile wierszy jest w #TaxInvoiceData? – Joe

+0

* Czy indeks wyszukiwania * - ok, ale na ** który indeks ** ??? Ponadto: mówisz '(ID, Field2, Field3)' są kluczem podstawowym twojego 'Table X' - czy ** indeks klastrowany ** również jest w tabeli? Czy to jest kupa? –

+0

W jaki sposób S dołącza do zapytania? Możliwe, że ponieważ klucz podstawowy nie jest klastrowany, szybsze jest przeskanowanie tabeli niż przeskok między indeksem a tabelą dla każdego wiersza. – idstam

Odpowiedz

5

Krótka odpowiedź: ponieważ optymalizator uważa byłoby szybciej.

Spróbujmy jednak przeczytać umysł optymalizatora.

Ponieważ nie podano pełnego schematu tabeli, zakładam, że istnieje indeks klastrowany na xxx.ID i że #TaxInvoiceData jest stertą. Oczekujesz planu, w którym indeks PK jest badany dla każdego wiersza w #TaxInvoiceData, ale wybierasz xxx.Field4, który będzie wymagał wyszukiwania zakładek dla każdego dopasowania. Może to spowodować 29 000 losowych żądań we/wy. Oooo.

Odwrotnie, SQL Server może (i najwyraźniej będzie) wykonać większą liczbę bardziej wydajnych operacji wejścia/wyjścia, wykonując skanowanie tabeli i prawdopodobnie wykona szybki skrót z #TaxInvoiceData.

Co więc można zrobić? Możesz utworzyć indeks obejmujący Field4. Lub możesz użyć indeksu i dołączyć wskazówki, aby wymusić plan, którego szukasz (ale podejrzewam, że wydajność nie byłaby tak dobra, jak masz nadzieję). Czy to zapytanie jest używane na tyle często, że daje problemy z wydajnością aplikacji lub po prostu chcesz wyeliminować skanowanie tabeli z zasady? Jeśli to drugie, może się okazać, że narzut pozbycia się skanu nie jest w końcu wart.


Edit:

Skoro już wspomniałem, że nie ma indeksu klastrowego na stole, to również może mieć wpływ na sposób efektywny wyszukiwań z indeksu są. Jeśli ta tabela nie jest bardzo obciążona, należy rozważyć zmianę PK w klastrze. Już samo to może zmienić plan, a nawet jeśli nie przyspieszy innych operacji z powodu zmniejszenia narzutów.

+0

Dziękuję za wyjaśnienie, z którym ludzie się zgadzają. Ale wybacz mojej niewiedzy Nie rozumiem, dlaczego Field4 robi różnicę, ponieważ jest to klauzula select, a nie tam, gdzie myślę, że działałoby w ten sposób, znajdź stronę/wiersz/liść według klauzuli where i chwyć pole z tego rząd. Nie rozumiem więc, w jaki sposób indeks pola 4 poprawi wyszukiwanie. Również nie ma żadnego indeksu klastrowanego, tylko PK, który został ustawiony na Non-clustered z jakiegokolwiek powodu. – Mike

+5

Jeśli wszystko, czego wymaga zapytanie, zawarte jest w indeksie, SQL Server może po prostu tam zajrzeć i całkowicie uniknąć używania tabeli. Nazywane jest to "wskaźnikiem pokrycia" dla zapytania i zwykle jest bardzo wydajne. Nie dotyczy to twojej sytuacji, ponieważ Field4 należy odczytać z tabeli. Problem polega na tym, że wielokrotne (wiele tysięcy razy) wyszukiwanie wiersza w tabeli, do którego odnosi się wiersz indeksu, nie jest zbyt wydajne z powodu narzutu we/wy. Optymalizator rozważa to wszystko, gdy decyduje, co zrobić. – zinglon

-2

Może przepisanie zapytania pomogłoby:

SELECT X.ID, X.Field4 
FROM xxx X, #TaxInvoiceData T 
WHERE X.Id = T.Id   
AND X.Field2 = @VAR    
AND X.Field3 = 'S' 
+0

Dzięki za czas, ale to nie zmieniło planu zapytania. – Mike

+6

To nie jest standardowa składnia "JOIN", przepisanie zapytania w ten sposób nie powinno mieć żadnego wpływu * i * pogorszyć kod, -1 – Matthew

Powiązane problemy