Miałem ten problem dawno temu, znalazłem obejście, które mi pasowało i zapomniałem o tym.
Ale teraz jest takie pytanie na SO, więc jestem skłonny poruszyć ten problem.
Istnieje widok, który łączy kilka tabel w bardzo prosty sposób (zamówienia + wiersze zamówień).
Zapytanie bez where
klauzuli powoduje zwrócenie kilku milionów wierszy.
Jednak nikt nigdy tak go nie nazywa. Zwykle jest to zapytanie
select * from that_nasty_view where order_number = 123456;
Zwraca około 10 rekordów z 5m.
Ważna rzecz: widok zawiera funkcję okna rank()
, która jest dokładnie podzielona na pola, za pomocą których widok jest zawsze odpytywany:
rank() over (partition by order_number order by detail_line_number)
Teraz, jeśli ten widok jest zapytany o dosłowne parametry w ciągu zapytania, dokładnie tak jak pokazano powyżej, natychmiast zwraca wiersze. Plan wykonania jest w porządku:
- Szukaj indeksu w obu tabelach przy użyciu indeksów
order_number
(zwraca 10 wierszy). - Obliczanie okien nad zwróconym drobnym wynikiem.
- Wybieranie
Jednak gdy widok jest wywoływany w sparametryzowany sposób, robi się nieprzyjemnie:
Index scan
we wszystkich tabelach ignorując indeksy. Zwraca 5m wierszy.- Ogromne dołączenie.
- Obliczanie okien dla wszystkich
partition
s (około 500k okien). Filter
wziąć 10 rzędów z 5 m.- Wybierz
Dzieje się tak we wszystkich przypadkach, gdy zaangażowane są parametry. Może to być SSMS:
declare @order_number int = 123456;
select * from that_nasty_view where order_number = @order_number;
Może to być klient ODBC, taki jak Excel:
select * from that_nasty_view where order_number = ?
Lub może to być dowolny inny klient, który używa parametrów, a nie konkatenacji SQL.
Jeśli funkcja okna zostanie usunięta z widoku, działa idealnie szybko, niezależnie od tego, czy jest pytana o parametry, czy nie.
Moim obejściem było usunięcie funkcji obrażającej i ponowne zastosowanie jej na późniejszym etapie.
Ale co daje? Czy to naprawdę błąd w działaniu funkcji okna przez SQL Server 2008?
order_number
nie jest kluczem podstawowym. Jest int not null
w nim indeks nieklastrowany w obu tabelach.
OPTION (RECOMPILE)
pomocy?