众所周知,SCHEMABINDING
一个函数可以避免更新计划中不必要的假脱机:
如果您使用不涉及任何表(即不访问数据)的简单 T-SQL UDF,请确保
SCHEMABINDING
在创建 UDF 期间指定选项。这将使 UDF 绑定模式并确保查询优化器不会为涉及这些 UDF 的查询计划生成任何不必要的假脱机运算符。
SCHEMABINDING
即使函数不访问数据,还有其他优点吗?
众所周知,SCHEMABINDING
一个函数可以避免更新计划中不必要的假脱机:
如果您使用不涉及任何表(即不访问数据)的简单 T-SQL UDF,请确保
SCHEMABINDING
在创建 UDF 期间指定选项。这将使 UDF 绑定模式并确保查询优化器不会为涉及这些 UDF 的查询计划生成任何不必要的假脱机运算符。
SCHEMABINDING
即使函数不访问数据,还有其他优点吗?
是的。
未能指定
WITH SCHEMABINDING
意味着 SQL Server 会跳过它通常对函数体进行的详细检查。它只是将该功能标记为访问数据(如问题中给出的链接中所述)。这是性能优化。如果它不做这个假设,SQL Server 将不得不对每个函数调用执行详细检查(因为未绑定的函数可能随时更改)。
有五个重要的函数属性:
例如,采用以下未绑定的标量函数:
我们可以使用元数据函数查看五个属性:
两个数据访问属性已设置为 true ,其他三个设置为 false。
这具有超出预期的影响(例如,在索引视图或索引计算列中使用)。
对查询优化器的影响
Determinism属性特别影响查询优化器。它有关于允许执行的重写和操作类型的详细规则,并且这些规则对于非确定性元素非常有限。副作用可能非常微妙。
例如,考虑以下两个表:
...以及使用该函数的查询(如前所述):
查询计划与预期一致,具有对表 T2 的搜索:
但是,如果使用派生表或公用表表达式编写相同的逻辑查询:
执行计划现在具有扫描功能,涉及函数的谓词卡在过滤器中:
如果派生表或公用表表达式被视图或内联函数替换,也会发生这种情况。提示(和其他类似
FORCESEEK
尝试)不会成功:根本问题是查询优化器不能随意重新排序不确定的查询元素。
为了产生一个搜索,过滤器谓词需要在计划中向下移动到 T2 数据访问。当函数是不确定的时,会阻止这种移动。
使固定
此示例的修复涉及两个步骤:
WITH SCHEMABINDING
第一步是微不足道的。第二个涉及从 string to 删除非确定性隐式强制转换
datetime
;用确定性替换它CONVERT
。两者都不够。函数属性现在是:
随着优化器的释放,所有示例现在都会生成所需的搜索计划。
请注意,在函数中使用
CAST
todatetime
是行不通的,因为无法在该语法中指定转换样式:此函数定义生成扫描计划,并且属性显示它仍然是不确定的: