MS SQL SELECT WHERE @Variable --> Laufzeit

Squicky

Lt. Commander
Registriert
Sep. 2002
Beiträge
1.405
Hallo

Folgende Situation:
Benutzt wird Microsoft SQL Server 2012.
Eine Tabelle (tab) hat 8 Spalten (sp1, sp2, …, sp8) und ca. 2.000.000 Zeilen.
„sp1“ ist von Typ „INT“.

Variante 1:
Code:
SELECT sp1, sp2, sp3, sp4
FROM tab
WHERE sp1 = 0

Variante 2:
Code:
DECLARE @x INT
SET @x = 0

SELECT sp1, sp2, sp3, sp4
FROM tab
WHERE sp1 = @x

Beide Varianten bringen das gleiche Ergebnis zurück (7 Zeilen).
Variante 1 braucht dafür (deutlich) weniger wie 1 Sekunde.
Variante 2 braucht dafür ca. 20 Sekunden.

Warum genau braucht Variante 2 so viel Zeit?

P.S.: Hier ist ein „dirty workaround“:
Variante 3:
Code:
DECLARE @x INT
SET @x = 0

DECLARE @s NVARCHAR(MAX)
SET @s = '
SELECT sp1, sp2, sp3, sp4
FROM tab
WHERE sp1 = ' + CAST(@x AS NVARCHAR(MAX))

EXEC(@s)

Variante 3 braucht ebenfalls wie Variante 1 (deutlich) weniger wie 1 Sekunde.

Warum "genau" braucht Variante 2 so viel Zeit?

Danke
 
Was sagt denn der Ausführungsplan im SQL Server Management Studio zu den jeweiligen Prozeduren?

Frage 2: sind alle Spalten die du in deinem WHERE verwendest indexiert?
 
Zuletzt bearbeitet:
Ehomer schrieb:
Was sagt denn der Ausführungsplan im SQL Server Management Studio zu den jeweiligen Prozeduren?

Frage 2: sind alle Spalten die du in deinem WHERE verwendest indexiert?

Hallo

Ein Index ist auf der Spalte sp1 vorhanden.

Warum sollte dies aber einen Unterschied machen?
In Variante 1 und Variante 2 werden die selben Spalten angezeicht und es wird nach der selben Spalte per WHERE gefiltert.

(Ausführungsplan kann ich erst in ein paar Tagen testen.)
 
Das ist das Standard verhalten von Datenbanken(egal ob ms,my,pg usw),
wenn sie ein prepared statement haben.

Ohne Ausführungsplan kann man da nicht mehr dazu sagen.
 
Bei mir funktioniert das tadellos. Egal welche Variante ich anwende, es wird immer schön der Index benutzt und das Query ist in ein paar ms durch.

Dein Ausführungsplan wird vermutlich zeigen, dass bei Variante 1 und 3 der Index benutzt wird, während er bei Variante 2 einen Full Table Scan hinlegt und den Index ignoriert. Das kann aber mehrere Gründe haben.

Einer wäre, dass der Plan für Variante 2 auf einem nicht selectiven Query basiert, in dem er sich entschieden hat den Index zu ignorieren da er sowieso von einer großen Range ausgeht und den Plan dann auch bei selectiven Parametern anwendet. Immerhin ist die abgefragte Spalte nicht unique, also ist die Möglichkeit gegeben.

Die Antwort steht eigentlich eh schon im verlinkten Artikel; einen Query- bzw. Index Hint mit angeben. Ist zwar ne Methode mim Hammer, aber wenn alle Stricke reißen kanns helfen. Du könntest auch ne Stored Procedure basteln und mit RECOMPILE oder OPTIMIZE FOR arbeiten.
 
Zuletzt bearbeitet:
Zurück
Oben