J'essaie de comprendre pourquoi l'utilisation d'une variable de table empêche l'optimiseur d'utiliser une recherche d'index puis une recherche de signet par rapport à une analyse d'index.
Remplir la table:
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)
Remplissez une variable de table avec un seul enregistrement et essayez de rechercher la clé primaire et la deuxième colonne en recherchant dans la colonne de clé étrangère:
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
Voici le plan d'exécution:
Maintenant, la même requête utilisant une table temporaire à la place:
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
Ce plan de requête utilise une recherche et recherche de signets:
Pourquoi l'optimiseur souhaite-t-il effectuer la recherche de signet avec la table temporaire, mais pas la variable de table?
La variable de table est utilisée dans cet exemple pour représenter les données provenant d'un type de table défini par l'utilisateur dans une procédure stockée.
Je me rends compte que la recherche d'indice pourrait ne pas être appropriée si la valeur de la clé étrangère s'est produite des centaines de milliers de fois. Dans ce cas, une analyse serait probablement un meilleur choix. Pour le scénario que j'ai créé, il n'y avait pas de ligne avec une valeur de 10. Je pense toujours que le comportement est intéressant et j'aimerais savoir s'il y a une raison à cela.
L'ajout OPTION (RECOMPILE)
n'a pas changé le comportement. L'UDDT possède une clé primaire.
@@VERSION
est SQL Server 2008 R2 (SP2) - 10.50.4042.0 (X64) (Build 7601: Service Pack 1) (Hyperviseur)