添加WITH SCHEMABINDING后UDF性能大幅提升的原因是什么?
我有一个复杂查询原本执行需要约10分钟,排查后发现是频繁调用的标量UDF拖慢了性能。给这个UDF添加WITH SCHEMABINDING后,查询仅需数秒就能完成。
该UDF代码如下:
ALTER FUNCTION dbo.GetMaxBatch() RETURNS INT WITH SCHEMABINDING AS BEGIN DECLARE @max_batch INT SELECT @max_batch = max(batch) FROM dbo.map RETURN @max_batch; END;
因为这个UDF在会话内返回值固定,我之前硬编码这个值时性能表现很好,添加SCHEMABINDING后也达到了同样的效果,想知道性能大幅提升的具体原因。
避免重复执行,实现结果复用:
未添加WITH SCHEMABINDING时,SQL Server无法确定这个UDF的返回值是否会随底层表的变化而改变,哪怕你清楚会话内值是固定的,优化器也只能每次调用UDF时重新执行里面的SELECT MAX(batch)聚合查询。如果复杂查询里频繁调用这个UDF,等于重复执行几十上百次聚合,这就是性能慢的核心原因。
加上WITH SCHEMABINDING后,SQL Server能确认UDF依赖的dbo.map结构不可随意修改,并且分析出该UDF的返回值在查询执行期间是恒定的(仅读取数据,无不确定依赖)。此时优化器会把UDF的执行提升到查询计划最外层,只执行一次MAX(batch),然后将结果缓存下来,所有调用处直接复用这个值,和你硬编码值的效果完全一致。优化器可整合UDF逻辑:
无SCHEMABINDING的标量UDF对优化器来说是“黑盒”,无法将UDF内部逻辑和外部主查询的计划合并优化,只能每次调用单独执行。而绑定架构的UDF,优化器可以“看穿”内部逻辑,将其与主查询的操作整合,不仅避免了多次执行的开销,甚至能把UDF的聚合逻辑和主查询的其他步骤合并,进一步提升效率。减少额外校验开销:
WITH SCHEMABINDING强制UDF依赖的对象(dbo.map)不能被删除或修改结构,这让SQL Server无需每次调用UDF时都去检查底层对象是否变化,减少了不必要的校验操作,间接提升了性能。
内容的提问来源于stack exchange,提问作者Guitoux

