Cela dépend.
Tout d'abord
Qu'est-ce qu'une expression de table commune ?
Un CTE (non récursif) est traité de manière très similaire aux autres constructions qui peuvent également être utilisées comme expressions de table en ligne dans SQL Server. Tables dérivées, vues et fonctions de table en ligne. Notez que bien que BOL indique qu'un CTE "peut être considéré comme un ensemble de résultats temporaire", il s'agit d'une description purement logique. Le plus souvent, il n'est pas matérialisé à part entière.
Qu'est-ce qu'une table temporaire ?
Il s'agit d'une collection de lignes stockées sur des pages de données dans tempdb. Les pages de données peuvent résider partiellement ou entièrement en mémoire. De plus, la table temporaire peut être indexée et avoir des statistiques de colonne.
Données de test
CREATE TABLE T(A INT IDENTITY PRIMARY KEY, B INT , F CHAR(8000) NULL);
INSERT INTO T(B)
SELECT TOP (1000000) 0 + CAST(NEWID() AS BINARY(4))
FROM master..spt_values v1,
master..spt_values v2;
Exemple 1
WITH CTE1 AS
(
SELECT A,
ABS(B) AS Abs_B,
F
FROM T
)
SELECT *
FROM CTE1
WHERE A = 780
Remarquez dans le plan ci-dessus qu'il n'y a aucune mention de CTE1. Il accède simplement aux tables de base directement et est traité de la même manière que
SELECT A,
ABS(B) AS Abs_B,
F
FROM T
WHERE A = 780
Réécrire en matérialisant le CTE dans une table temporaire intermédiaire ici serait massivement contre-productif.
Matérialisation de la définition CTE de
SELECT A,
ABS(B) AS Abs_B,
F
FROM T
Cela impliquerait de copier environ 8 Go de données dans une table temporaire, il y a toujours la surcharge de la sélection également.
Exemple 2
WITH CTE2
AS (SELECT *,
ROW_NUMBER() OVER (ORDER BY A) AS RN
FROM T
WHERE B % 100000 = 0)
SELECT *
FROM CTE2 T1
CROSS APPLY (SELECT TOP (1) *
FROM CTE2 T2
WHERE T2.A > T1.A
ORDER BY T2.A) CA
L'exemple ci-dessus prend environ 4 minutes sur ma machine.
Seules 15 lignes sur les 1 000 000 de valeurs générées aléatoirement correspondent au prédicat, mais l'analyse coûteuse de la table se produit 16 fois pour les localiser.
Ce serait un bon candidat pour matérialiser le résultat intermédiaire. La réécriture équivalente de la table temporaire a pris 25 secondes.
INSERT INTO #T
SELECT *,
ROW_NUMBER() OVER (ORDER BY A) AS RN
FROM T
WHERE B % 100000 = 0
SELECT *
FROM #T T1
CROSS APPLY (SELECT TOP (1) *
FROM #T T2
WHERE T2.A > T1.A
ORDER BY T2.A) CA
La matérialisation intermédiaire d'une partie d'une requête dans une table temporaire peut parfois être utile même si elle n'est évaluée qu'une seule fois - lorsqu'elle permet de recompiler le reste de la requête en profitant des statistiques sur le résultat matérialisé. Un exemple de cette approche se trouve dans l'article SQL Cat Quand décomposer les requêtes complexes.
Dans certaines circonstances, SQL Server utilisera un spool pour mettre en cache un résultat intermédiaire, par ex. d'un CTE, et éviter d'avoir à réévaluer ce sous-arbre. Ceci est abordé dans l'élément Connect (migré) Fournir un indice pour forcer la matérialisation intermédiaire des CTE ou des tables dérivées. Cependant, aucune statistique n'est créée à ce sujet et même si le nombre de lignes spoolées devait être très différent de l'estimation, il n'est pas possible que le plan d'exécution en cours s'adapte dynamiquement en réponse (au moins dans les versions actuelles. Les plans de requête adaptatifs peuvent devenir possibles dans l'avenir).