J.D*_*.D. 32 performance sql-server cte execution-plan query-performance
查询中未使用的 CTE 是否会影响性能和/或更改生成的查询计划?
Sol*_*zky 28
+1 给 Erik,但想添加两件事(在评论中效果不佳):
您甚至不需要查看执行计划就可以看到它们在不使用时被忽略。以下应该产生“除以 0”错误,但不会因为cte2根本没有被选中:
;WITH cte1 AS
(
SELECT 1 AS [Bob]
),
cte2 AS (
SELECT 1 / 0 AS [Err]
FROM cte1
)
SELECT *
FROM cte1;
Run Code Online (Sandbox Code Playgroud)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;
Run Code Online (Sandbox Code Playgroud)关于性能,未使用的 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
Run Code Online (Sandbox Code Playgroud)
当做完所有事情都没有执行时,就会出现一个问题:
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'.
*/
Run Code Online (Sandbox Code Playgroud)
Eri*_*ing 21
他们似乎没有这样做,但这实际上只适用于嵌套的 CTE。
创建两个临时表:
CREATE TABLE #t1 (id INT);
INSERT #t1 ( id )
VALUES ( 1 );
CREATE TABLE #t2 (id INT);
INSERT #t2 ( id )
VALUES ( 1 );
Run Code Online (Sandbox Code Playgroud)
查询 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;
Run Code Online (Sandbox Code Playgroud)
查询 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;
Run Code Online (Sandbox Code Playgroud)
查询计划:
有开销,但是查询的不必要部分很早就被消除了(在这种情况下是在解析期间;在更复杂情况下是简化阶段),因此额外的工作确实很少,并且不会导致潜在的基于成本的昂贵优化。
| 归档时间: |
|
| 查看次数: |
3567 次 |
| 最近记录: |