Зависи.
Преди всичко
Какво е общ табличен израз?
(нерекурсивният) CTE се третира много подобно на други конструкции, които също могат да се използват като вградени таблични изрази в SQL Server. Функции с извлечени таблици, изгледи и вградени таблици. Имайте предвид, че докато BOL казва, че CTE "може да се разглежда като временен набор от резултати", това е чисто логическо описание. По-често той не е материализиран сам по себе си.
Какво е временна таблица?
Това е колекция от редове, съхранявани на страници с данни в tempdb. Страниците с данни могат да се намират частично или изцяло в паметта. Освен това временната таблица може да бъде индексирана и да има статистически данни за колони.
Тестови данни
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;
Пример 1
WITH CTE1 AS
(
SELECT A,
ABS(B) AS Abs_B,
F
FROM T
)
SELECT *
FROM CTE1
WHERE A = 780
Забележете, че в плана по-горе не се споменава CTE1. Той просто има директен достъп до базовите таблици и се третира по същия начин като
SELECT A,
ABS(B) AS Abs_B,
F
FROM T
WHERE A = 780
Пренаписването чрез материализиране на CTE в междинна временна таблица тук би било изключително непродуктивно.
Материализиране на дефиницията на CTE на
SELECT A,
ABS(B) AS Abs_B,
F
FROM T
Би включвало копиране на около 8 GB данни във временна таблица, след което все още има допълнителни разходи за избор от нея.
Пример 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
Горният пример отнема около 4 минути на моята машина.
Само 15 реда от 1 000 000 произволно генерирани стойности съвпадат с предиката, но скъпото сканиране на таблицата се извършва 16 пъти, за да ги открие.
Това би било добър кандидат за материализиране на междинния резултат. Пренаписването на еквивалентната временна таблица отне 25 секунди.
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
Междинното материализиране на част от заявка във временна таблица понякога може да бъде полезно, дори ако се оценява само веднъж - когато позволява на останалата част от заявката да бъде прекомпилирана, като се възползва от статистиката за материализирания резултат. Пример за този подход е в статията за SQL Cat Кога да разбиете сложни заявки.
При някои обстоятелства SQL Server ще използва пул за кеширане на междинен резултат, напр. на CTE и избягвайте да преоценявате това поддърво. Това се обсъжда в (мигрирания) елемент Свързване Предоставете намек за принудително междинно материализиране на CTE или производни таблици. Въпреки това не се създават статистически данни за това и дори ако броят на буферираните редове трябваше да бъде значително различен от прогнозния, не е възможно планът за изпълнение в ход да се адаптира динамично в отговор (поне в текущите версии. Адаптивните планове за заявки може да станат възможни в бъдещето).