2009-08-31 6 views

Odpowiedz

19

Bez żadnych szczegółów trudno jest odgadnąć, na czym polega problem, a nawet czy w ogóle jest problem. Wybór skanowania zamiast poszukiwania może być spowodowany wieloma czynnikami:

  • Zapytanie wyraża zestaw wyników obejmujący całą tabelę. To znaczy. zapytanie jest proste: SELECT * FROM <table>. Jest to trywialny przypadek, który byłby doskonale objęty skanowaniem indeksu klastrowego bez potrzeby uwzględniania niczego innego.
  • optymalizator nie ma alternatywy:
    • zapytanie wyraża podzbiór całej tabeli, ale orzecznik filtrowanie jest na kolumnach, które nie są częścią klastra kluczem i nie ma non-clustred indeksy na tych kolumnach zarówno. Nie jest to alternatywny plan inny niż pełne skanowanie.
    • Zapytanie ma predykaty filtrowania na kolumnach w kluczu indeks clustred, ale nie są one SARGable. Predykat filtrowania zwykle musi zostać przepisany, aby był SARGable, właściwe przepisanie zależy od przypadku. Bardziej subtelny problem może pojawić się z powodu niejawnych reguł konwersji, np. predykat filtrowania to WHERE column = @value, ale kolumna to VARCHAR (Ascii), a wartość @ to NVARCHAR (kod Unicode).
    • Zapytanie ma predykaty filtrowania SARGale dla kolumn w kluczu klastrowym, ale kolumna po lewej stronie nie jest filtrowana. To znaczy. indeks klastrowy znajduje się w kolumnach (foo, bar), ale klauzula WHERE jest dostępna tylko na bar.
  • Optymalizator wybiera skan.
    • Gdy alternatywą jest nieklastrowanym indeks następnie zeskanować (lub zakres poszukiwania), ale wybór jest użycie indeksu klastrowego przyczyną może być zwykle wytropił do index tipping point powodu braku nieklastrowanym pokrycie indeksu dla projekcji zapytania. Zauważ, że to nie jest twoje pytanie, ponieważ spodziewasz się wyszukiwania w indeksie klastrowym, a nie indeksowania nieobjętego klastrami (przypisanie pytania jest w 100% dokładne i udokumentowane ...)
    • Oszacowania liczności. Estymacja kosztu zapytań jest oparta na statystyce (indeksach) kluczy klastra, która zapewnia oszacowanie mocy zbioru (tj. Ile wierszy będzie pasować). Na proste zapytanie To nie może się zdarzyć, ponieważ każde oszacowanie wyszukiwania lub poszukiwania zakresu będzie niższe niż w przypadku skanowania, niezależnie od statystyk, ale w przypadku zapytania o złożeniu z łączeniami i filtrami na wielu tabelach , rzeczy są bardziej złożone i plan może zawierać skanowanie, w którym oczekiwano przeszukiwania, ponieważ optymalizator zapytań może wybrać plan, w którym kolejność oceny łączenia jest odwrócona do tego, czego oczekuje obserwator. Wybór kolejności odwrotnej może być poprawiony (najczęściej) lub może być problematyczny (zwykle ze względu na przestarzałe statystyki lub na wąchanie parametrów).
    • Gwarancja na zamówienie. Skanowanie da wyniki w gwarantowanej kolejności, a elementy wyżej w drzewie wykonania mogą skorzystać z tego zamówienia (np. Sortowanie lub buforowanie może zostać wyeliminowane lub może być użyte sprzężenie scalające zamiast skrótów/zagnieżdżonych). Ogólnie rzecz biorąc, koszt zapytania jest lepszy w wyniku wybrania wyraźnie wolniej dostępnej ścieżki.

Są kilka krótkich wskazówek dlaczego klastra skanowania indeksu mogą być obecne, gdy oczekuje się indeksu klastrowego szukać. Pytanie jest wyjątkowo ogólne i niemożliwe jest udzielenie odpowiedzi "dlaczego", poza poleganiem na 8 kulkach. Teraz, jeśli zadam twoje pytanie, aby było poprawnie udokumentowane i poprawnie wyartykułowane, wtedy oczekiwanie na indeks klastrowany: szuka oznacza, że ​​szukasz unikalnego rekordu opartego na wartości klucza clustred. W tym przypadku problem musi dotyczyć SARGability klauzuli WHERE.

+0

"Na proste zapytanie To nie może się zdarzyć, ponieważ jakikolwiek szacunek wyszukiwania lub poszukiwania zakresu będzie niższy niż dla skanowania" ... nie jest prawdą ... Jeśli tylko 10% wierszy ma wartość 'Specjalna = prawda (1) ', następnie proste zapytanie' Wybierz * Z tabeli, gdzie Special = 0' Zawsze wybierze tabelę Skanuj. Dzieje się tak nawet wtedy, gdy indeks istnieje w kolumnie Specjalnej, o ile indeks nie jest indeksem klastrowym. (Jeśli indeks jest indeksem klastrowym, wówczas optymalizator oczywiście wybierze zakres wyszukiwania.) –

+0

@Charles: ale jest to "punkt indeksowania" w pracy, o którym wspomniałem. Btw, twoje przykładowe zapytanie nie jest "proste" (np. Trivial, zobacz http://msdn.microsoft.com/en-us/library/aa226174%28SQL.70%29.aspx): "instrukcja SELECT, w której wszystkie kolumny znajdują się w unikalnym indeksie obejmującym i nie ma innego indeksu, który ma ten zestaw kolumn w nim. " –

+0

jeśli to, co masz na myśli przez "Prosty", to mogę się zgodzić technicznie, ale w kontekście, bez wyjaśnień co do twojego znaczenia słowa "prosty" czytelnik dostałby zupełnie innego i niepoprawnego wrażenia. Jeśli umieścisz słowo "proste" w cudzysłowie lub podświetlone, z definicją roku w parens lub jako przypis, to dobrze ... W przeciwnym razie czytelnik zakłada, że ​​każde "proste" zapytanie nie będzie miało tego problemu, a to jest nieprawidłowe, dla powody, o których wspomniałeś. ... aby zaostrzyć problem, należy częściowo zdefiniować kompleks jako związany ze złożonością sprzężenia, który nie jest związany z problemem przechylania. –

5

Jeśli zapytanie incldues więcej niż pewien procent wierszy w tabeli, optymalizator wybiera zrobić skan zamiast szukać, ponieważ przewiduje, że będzie w takim przypadku wymaga mniejszej liczby operacji wejścia (dla poszukiwacza, potrzebuje jednego IO dysku na każdy poziom w indeksie dla każdego zwracanego przez siebie wiersza), podczas gdy w przypadku skanowania istnieje tylko jedno miejsce docelowe dysku na wiersz w całej tabeli.

Więc jeśli istnieje 5 poziomów w indeksie b-drzewa, to jeśli zapytanie wygeneruje więcej niż 20% wierszy w tabeli, taniej jest odczytać całą tabelę niż zrobić 5 OI dla każdego wierszy 20% ...

Czy można nieco zawęzić dane wyjściowe zapytania, aby zmniejszyć liczbę wierszy zwracanych przez ten krok w procesie? Pomogłoby to wybrać szukanie przez skan.