2012-05-15 25 views
5

Mam podwójne zapytanie o samo łączenie, w którym wydajność jest poważnie pogorszona po zamianie wartości wyszukiwania.Wydajność zapytania SQL ulega pogorszeniu W zależności od kolejności wartości wyszukiwania

-- 500,000 i/o & 500ms execution 
select 
    fooA.ID 
    , fooB.ID 
from 
    foo AS fooA 
    INNER JOIN bar AS barA ON fooA.barID = barA.barID 
    INNER JOIN foo AS fooB ON fooA.fooID = fooB.fooID -- self join 
    INNER JOIN bar AS barB ON fooB.barID = barB.barID 
where 
    barA.value = 'xyz' 
    AND barB.value = '60' 

-- 5,000 i/o & 5ms execution 
select 
    fooA.ID 
    , fooB.ID 
from 
    foo AS fooA 
    INNER JOIN bar AS barA ON fooA.barID = barA.barID 
    INNER JOIN foo AS fooB ON fooA.fooID = fooB.fooID -- self join 
    INNER JOIN bar AS barB ON fooB.barID = barB.barID 
where 
    barA.value = '60' 
    AND barB.value = 'xyz' 
  • Wartość "xyz" znajduje się na liście 150000 razy w "bar" tabeli.
  • Wartość "60" jest wyświetlana 500 razy w tabeli "słupkowej".
  • Plany kwerend są takie same, z tym że najbardziej wewnętrzna pętla zwraca 150 000 wierszy lub 500 wierszy, w zależności od tego, która wartość wyszukiwania jest wymieniona jako pierwsza.
  • Wykonywane wyszukiwania szukają indeksów nieklastrowych.
  • Statystyki zostały zaktualizowane na obu tabelach przy użyciu FULLSCAN.

Dlaczego optymalizator zapytań SQL nie identyfikuje poprawnie, że w obu przypadkach najbardziej wewnętrzną częścią planu kwerendy powinna być ta z najmniejszą liczbą wierszy?

+0

Kryteria, które ograniczają liczbę wierszy w zapytaniu, najczęściej są pierwsze. Jest to ogólna zasada. – JonH

+1

Możliwa odpowiedź: parametryzacja zapytania, sniffowanie parametrów i ponowne użycie planu. –

+0

Czy można utworzyć klucze podstawowe ids na tabelach foo i bar? –

Odpowiedz

3

SQL Server nie rekompiluje kwerendy za każdym razem, gdy jest wykonywany. Robi to raz i jest zoptymalizowany pod kątem dokładnych wartości, jakie widzi po raz pierwszy. Domyślam się, że masz niefortunny plan zapisany w pamięci podręcznej.

Spróbuj dodać OPTION (RECOMPILE) na końcu.

+0

Dodałem to i nie było żadnej zmiany. Szacowana liczba wierszy od najbardziej wewnętrznego połączenia wynosi 2500 dla obu planów zapytań, ale rzeczywisty jest znacznie inny. –

+0

To dziwne. Oszacowanie liczebności indeksów dla dopasowania równości jest zazwyczaj bardzo dokładne. Czy tabele, których szukasz, zawierają bardzo dużą liczbę wierszy z bardzo małą ilością duplikatów? – usr

+0

Naprawdę nie widzę niczego, co mogłoby spowodować kłopoty. Czy możesz publikować zrzuty ekranu z dwóch rzeczywistych planów wykonania? – usr