Ich habe einen SP mit einem Parameter, der NULL als Standardwert hat, und dann möchte ich eine Abfrage wie folgt durchführen:
SELECT ...
FROM ...
WHERE a.Blah = @Blah AND (a.VersionId = @VersionId OR (@VersionId IS NULL AND a.VersionId IS NULL));
Das WHERE
obige prüft sowohl auf einen Nicht-NULL-Wert als auch auf einen NULL-Wert für @VersionId
.
Wäre es in Bezug auf die Leistung besser, stattdessen eine IF
Anweisung zu verwenden und die Abfrage in eine zu duplizieren, die nach Nicht-NULL und eine andere nach NULL sucht? :
IF @VersionId IS NULL BEGIN
SELECT ...
FROM ...
WHERE a.Blah = @Blah AND a.VersionId IS NULL;
ELSE BEGIN
SELECT ...
FROM ...
WHERE a.Blah = @Blah AND a.VersionId = @VersionId;
END
Oder das Abfrageoptimierungsprogramm macht es im Wesentlichen gleich?
AKTUALISIEREN:
(Hinweis: Ich verwende SQL Server.)
(Und soweit ich weiß, a.VersionId = @VersionId
funktioniert die Verwendung in beiden Fällen nicht, oder?)
sql-server-2008
performance
user2173353
quelle
quelle
Antworten:
Dieses Muster
kann durch ersetzt werden
Auf diese Weise können Sie eine NULL mit einer NULL abgleichen und die Engine kann einen Index
column
effizient verwenden. Für eine hervorragende eingehende Analyse dieser Technik verweise ich Sie auf den Blog-Artikel von Paul White:Da es in Ihrem speziellen Fall zwei Argumente gibt, können Sie dieselbe Matching-Technik verwenden, mit der
@Blah
Sie die gesamte WHERE-Klausel mehr oder weniger präzise umschreiben können:Dies funktioniert schnell, wenn ein Index aktiviert ist
(a.Blah, a.VersionId)
.In diesem Fall ja. In allen Versionen (mindestens) ab SQL Server 2005 kann das Optimierungsprogramm das Muster erkennen
col = @var OR (@var IS NULL AND col IS NULL)
und durch den richtigenIS
Vergleich ersetzen . Dies hängt von der internen Anpassung des Überschreibens ab, sodass es komplexere Fälle geben kann, in denen dies nicht immer zuverlässig ist.In Versionen von SQL Server ab einschließlich 2008 SP1 CU5 haben Sie auch die Möglichkeit, die Optimierung für das Einbetten von Parametern über zu verwenden
OPTION (RECOMPILE)
, wobei der Laufzeitwert eines beliebigen Parameters oder einer Variablen vor dem Kompilieren als Literal in die Abfrage eingebettet wird.Zumindest weitgehend ist die Wahl in diesem Fall eine Frage des Stils, obwohl die
INTERSECT
Konstruktion unbestreitbar kompakt und elegant ist.Die folgenden Beispiele zeigen den gleichen Ausführungsplan für jede Variation (Literale und variable Referenzen ausgeschlossen):
quelle