Abfrage ist schnell mit direktem Vergleich, aber nicht mit Tabellenvergleich mit demselben Spaltenindex

Ich habe eine ziemlich komplexe Abfrage, die einen direkten Vergleich mit @EventId macht, falls vorhanden und schnell, da es die gruppierte Indexzeile packt. Allerdings muss ich manchmal eine Gruppe dieser Event-IDs machen und die zweite Zeile dauert fast 30 Sekunden. Ich dachte, es würde genauso funktionieren, wenn man den Primärschlüssel nachsieht. Gibt es einen Grund, warum es so viel langsamer ist?

DECLARE @EventIds TABLE(Id INT NOT NULL); WHERE (@EventId IS NULL OR (ev.Id = @EventId)) AND (NOT EXISTS(SELECT 1 FROM @EventIds) OR ev.Id IN (SELECT * FROM @EventIds)) 

Es gibt keinen wirklich guten Grund, den Ausdruck zu haben

 NOT EXISTS(SELECT 1 FROM @EventIds) OR ev.Id IN (SELECT * FROM @EventIds) 

Der erste Ausdruck, auch wenn true, schließt die Auswertung des zweiten Ausdrucks nicht aus, da SQL server keine booleschen Ausdrücke verknüpft.

Zweitens, da Tabellenvariablen bekanntermaßen schlechte Ausführungspläne aufgrund errorshafter Statistiken und Zeilenanzahl verursacht haben. Bitte beachten Sie diesen Aufsatz über den Unterschied zwischen Tabellenvariablen und temporären Tabellen , Themen: Kardinalität und keine Spaltenstatistik .

Es könnte helfen, den folgenden Abfragehinweis am Ende der Abfrage hinzuzufügen:

 OPTION(RECOMPILE); 

Ja, das kompliziert den Plan jedes Mal, aber wenn du schreckliche performance bekommst, ist die kleine zusätzliche Kompilierzeit nicht so wichtig.

Dieser @EventId wird auch empfohlen, wenn Sie optionale Filter haben, wie Sie mit @EventId .

Es kann auch dazu beitragen, einen Primärschlüssel auf Id , der auf der @EventIds Tabellenvariable definiert ist. Dies würde ein Index-Suchvorgang statt eines Tabellen-Scans ermöglichen.