답변:
그들이하는 것처럼 보이지는 않지만 이것은 실제로 중첩 된 CTE에만 적용됩니다.
두 임시 테이블을 만듭니다.
CREATE TABLE #t1 (id INT);
INSERT #t1 ( id )
VALUES ( 1 );
CREATE TABLE #t2 (id INT);
INSERT #t2 ( id )
VALUES ( 1 );
쿼리 1 :
WITH your_mom AS (
SELECT TOP 1 *
FROM #t1 AS t
),
also_your_mom AS (
SELECT TOP 1 *
FROM #t2 AS t
)
SELECT *
FROM your_mom;
쿼리 2 :
WITH your_mom AS (
SELECT TOP 1 *
FROM #t1 AS t
),
also_your_mom AS (
SELECT TOP 1 *
FROM #t2 AS t
)
SELECT *
FROM also_your_mom;
쿼리 계획 :
오버 헤드가 있지만 쿼리의 불필요한 부분은 매우 일찍 제거됩니다 (이 경우 구문 분석 중, 더 복잡한 경우 단순화 단계). 추가 작업이 최소화되고 잠재적으로 비용이 많이 드는 비용 기반에 기여하지 않습니다 최적화.
Erik에게 +1하지만 두 가지를 추가하고 싶었습니다 (주석에서 잘 작동하지 않음).
사용하지 않을 때 무시되는 것을 확인하기 위해 실행 계획을 볼 필요조차 없습니다. 다음은 "0으로 나누기"오류를 발생 시키지만 cte2
전혀 선택 하지 않았기 때문에 발생하지 않습니다 .
;WITH cte1 AS
(
SELECT 1 AS [Bob]
),
cte2 AS (
SELECT 1 / 0 AS [Err]
FROM cte1
)
SELECT *
FROM cte1;
CTE의 그들이 유일한 CTE 경우에도 그들이에서 선택하더라도 무시할 수 있다면 논리적으로 모든 행 어쨌든 제외된다. 다음은 쿼리 최적화 프로그램이 CTE에서 행을 반환 할 수 없다는 것을 미리 알고 있으므로 실행하는 데 방해가되지 않습니다.
;WITH cte AS
(
SELECT 1 / 0 AS [Bob]
)
SELECT TOP (1) [object_id]
FROM sys.objects
UNION ALL
SELECT cte.[Bob]
FROM cte
WHERE 1 = 0;
성능과 관련하여 사용되지 않은 CTE는 구문 분석 및 컴파일 (또는 적어도 아래의 경우에는 컴파일)되므로 100 % 무시되지 않지만 비용은 무시해도되며 걱정할 가치가 없습니다.
구문 분석 만 할 때 오류가 없습니다.
SET PARSEONLY ON;
;WITH cte1 AS
(
SELECT obj.[NotHere]
FROM sys.objects obj
)
SELECT TOP (1) so.[name]
FROM sys.objects so
GO
SET PARSEONLY OFF;
GO
실행이 짧은 모든 것을 할 때 문제가 있습니다.
GO
SET NOEXEC ON;
GO
;WITH cte1 AS
(
SELECT obj.[NotHere]
FROM sys.objects obj
)
SELECT TOP (1) so.[name]
FROM sys.objects so
GO
SET NOEXEC OFF;
GO
/*
Msg 207, Level 16, State 1, Line XXXXX
Invalid column name 'NotHere'.
*/
NEWID()
UDF에서 사용하기 위해 뷰를 배치하는 트릭이 옵티마이 저가 캐싱하기 때문에 여러 호출에서 동일한 값을 반환 할 수있는 곳을 보았습니다 .