Ich versuche zu verstehen, warum die Verwendung einer Tabellenvariablen den Optimierer daran hindert, eine Indexsuche und dann eine Lesezeichensuche im Vergleich zu einer Indexsuche durchzuführen.
Auffüllen der Tabelle:
CREATE TABLE dbo.Test
(
RowKey INT NOT NULL PRIMARY KEY,
SecondColumn CHAR(1) NOT NULL DEFAULT 'x',
ForeignKey INT NOT NULL
)
INSERT dbo.Test
(
RowKey,
ForeignKey
)
SELECT TOP 1000000
ROW_NUMBER() OVER (ORDER BY (SELECT 0)),
ABS(CHECKSUM(NEWID()) % 10)
FROM sys.all_objects s1
CROSS JOIN sys.all_objects s2
CREATE INDEX ix_Test_1 ON dbo.Test (ForeignKey)
Füllen Sie eine Tabellenvariable mit einem einzelnen Datensatz und versuchen Sie, den Primärschlüssel und die zweite Spalte nachzuschlagen, indem Sie in der Fremdschlüsselspalte suchen:
DECLARE @Keys TABLE (RowKey INT NOT NULL)
INSERT @Keys (RowKey) VALUES (10)
SELECT
t.RowKey,
t.SecondColumn
FROM
dbo.Test t
INNER JOIN
@Keys k
ON
t.ForeignKey = k.RowKey
Unten ist der Ausführungsplan:
Nun die gleiche Abfrage mit einer temporären Tabelle:
CREATE TABLE #Keys (RowKey INT NOT NULL)
INSERT #Keys (RowKey) VALUES (10)
SELECT
t.RowKey,
t.SecondColumn
FROM
dbo.Test t
INNER JOIN
#Keys k
ON
t.ForeignKey = k.RowKey
Dieser Abfrageplan verwendet eine Suche und eine Lesezeichensuche:
Warum ist der Optimierer bereit, die Lesezeichensuche mit der temporären Tabelle, aber nicht mit der Tabellenvariablen durchzuführen?
Die Tabellenvariable wird in diesem Beispiel verwendet, um Daten darzustellen, die über einen benutzerdefinierten Tabellentyp in einer gespeicherten Prozedur eingehen.
Mir ist klar, dass die Indexsuche möglicherweise nicht geeignet ist, wenn der Fremdschlüsselwert hunderttausend Mal vorkommt. In diesem Fall wäre ein Scan wahrscheinlich die bessere Wahl. Für das von mir erstellte Szenario gab es keine Zeile mit dem Wert 10. Ich finde das Verhalten immer noch interessant und würde gerne wissen, ob es einen Grund dafür gibt.
Das Hinzufügen OPTION (RECOMPILE)
hat das Verhalten nicht geändert. Der UDDT hat einen Primärschlüssel.
@@VERSION
ist SQL Server 2008 R2 (SP2) - 10.50.4042.0 (X64) (Build 7601: Service Pack 1) (Hypervisor)