Estoy tratando de entender por qué el uso de una variable de tabla impide que el optimizador use una búsqueda de índice y luego la búsqueda de marcadores frente a una exploración de índice.
Poblar la mesa:
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)
Rellene una variable de tabla con un único registro e intente buscar la clave primaria y la segunda columna buscando en la columna de clave externa:
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
A continuación se muestra el plan de ejecución:
Ahora la misma consulta usando una tabla temporal en su lugar:
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
Este plan de consulta utiliza una búsqueda y búsqueda de marcadores:
¿Por qué el optimizador está dispuesto a hacer la búsqueda de marcadores con la tabla temporal, pero no con la variable de la tabla?
La variable de tabla se usa en este ejemplo para representar datos que provienen de un tipo de tabla definida por el usuario en un procedimiento almacenado.
Me doy cuenta de que la búsqueda del índice podría no ser apropiada si el valor de la clave externa se produjo cientos de miles de veces. En ese caso, un escaneo probablemente sería una mejor opción. Para el escenario que creé, no había una fila con un valor de 10. Todavía creo que el comportamiento es interesante y me gustaría saber si hay una razón para ello.
Agregar OPTION (RECOMPILE)
no cambió el comportamiento. El UDDT tiene una clave primaria.
@@VERSION
es SQL Server 2008 R2 (SP2) - 10.50.4042.0 (X64) (compilación 7601: Service Pack 1) (hipervisor)