为何非持久化计算列的函数调用未出现在实际执行计划中?
问题描述
我有一张包含非持久化计算列的表,创建语句如下:
create table dbo.Cases ( ... CaseName varchar(20) not null, NickName AS (dbo.fn_ParseCaseNickName(CaseName)), ... )
执行以下查询:
SELECT TOP 10 c.NickName, * FROM dbo.Cases c (NOLOCK) WHERE c.ID_Case = 294426
得到的实际执行计划中未显示fn_ParseCaseNickName函数的相关信息,但在SSMS中查看预估执行计划时,却能看到该函数的执行记录。请问为何实际执行计划中看不到该函数?
解答
这是SQL Server对非持久化计算列的处理逻辑,以及预估、实际执行计划生成机制的差异导致的:
非持久化计算列的按需计算特性:非持久化计算列不会将计算结果存储在表中,只有在需要返回该列数据时才会触发函数计算。你的查询中,数据库引擎先通过
ID_Case=294426快速定位目标行,之后才会对该行计算NickName的值,这个行级计算是嵌入在结果返回步骤中的,不会被拆分为独立的执行节点。预估执行计划的静态分析逻辑:预估计划是在查询编译阶段生成的,它会静态解析计算列的定义,将依赖的标量函数
fn_ParseCaseNickName作为逻辑依赖展示出来——不管实际执行时的计算量大小,它都会把编译时识别到的依赖关系列出来。实际执行计划的精简展示规则:实际执行计划只记录执行过程中独立的、可监控的执行运算符。标量UDF在非持久化计算列中的行级调用,会被合并到“获取行并生成结果集”的步骤里,不会单独生成函数执行的节点,所以你看不到函数的相关记录。如果直接在SELECT列表中调用该函数(而非通过计算列),或者函数被多次调用触发了特定优化逻辑,实际计划才会显示对应的函数执行节点。
内容的提问来源于stack exchange,提问作者AngryHacker
相关产品推荐
相关产品推荐

