Ich hatte dieses Problem vor langer Zeit, fand eine Problemumgehung, die zu mir passte, und vergaß es.
Aber jetzt gibt es diese Frage zu SO, also bin ich bereit, dieses Problem anzusprechen.
Es gibt eine Ansicht, die einige Tabellen auf sehr einfache Weise verbindet (Bestellungen + Bestellpositionen).
Bei einer Abfrage ohne where
Klausel gibt die Ansicht mehrere Millionen Zeilen zurück.
Niemand nennt es jedoch jemals so. Die übliche Abfrage ist
select * from that_nasty_view where order_number = 123456;
Dies gibt ungefähr 10 Datensätze von 5 m zurück.
Wichtig: Die Ansicht enthält eine Fensterfunktion rank()
, die genau nach dem Feld unterteilt ist, mit dem die Ansicht immer abgefragt wird:
rank() over (partition by order_number order by detail_line_number)
Wenn diese Ansicht nun genau wie oben gezeigt mit Literalparametern in der Abfragezeichenfolge abgefragt wird, werden die Zeilen sofort zurückgegeben. Der Ausführungsplan ist in Ordnung:
- Indexsuche für beide Tabellen unter Verwendung der Indizes auf
order_number
(gibt 10 Zeilen zurück). - Berechnen von Fenstern über dem zurückgegebenen winzigen Ergebnis.
- Auswählen.
Wenn die Ansicht jedoch parametrisiert aufgerufen wird, werden die Dinge unangenehm:
Index scan
auf allen Tabellen ohne Indizes. Gibt 5 m Zeilen zurück.- Riesige Verbindung.
- Berechnen von Fenstern über alle
partition
s (ca. 500.000 Fenster). Filter
10 Reihen aus 5m nehmen.- Wählen
Dies geschieht in allen Fällen, wenn Parameter beteiligt sind. Es kann SSMS sein:
declare @order_number int = 123456;
select * from that_nasty_view where order_number = @order_number;
Es kann sich um einen ODBC-Client wie Excel handeln:
select * from that_nasty_view where order_number = ?
Oder es kann ein anderer Client sein, der Parameter und keine SQL-Verkettung verwendet.
Wenn die Fensterfunktion aus der Ansicht entfernt wird, wird sie einwandfrei ausgeführt, unabhängig davon, ob sie mit Parametern abgefragt wird oder nicht.
Meine Problemumgehung bestand darin, die fehlerhafte Funktion zu entfernen und zu einem späteren Zeitpunkt erneut anzuwenden.
Aber was gibt es? Ist es wirklich ein Fehler, wie SQL Server 2008 mit Fensterfunktionen umgeht?
order_number
ist kein Primärschlüssel. int not null
In beiden Tabellen befindet sich ein nicht gruppierter Index.
OPTION (RECOMPILE)
?