除万圣节保护外,SCHEMABINDING功能还有什么好处?


52

众所周知,SCHEMABINDING函数可以避免更新计划中不必要的假脱机

如果您使用的是不触摸任何表(即不访问数据)的简单T-SQL UDF,请确保SCHEMABINDING在创建UDF时指定了该选项。这将使UDF成为模式绑定,并确保查询优化器不会为涉及这些UDF的查询计划生成任何不必要的假脱机操作符。

SCHEMABINDING即使不访问数据,该功能还有其他优点吗?

Answers:


78

是。

未能指定WITH SCHEMABINDING意味着SQL Server跳过了通常在功能主体上进行的详细检查。它只是将函数标记为正在访问数据(如问题中给出的链接所述)。

这是性能优化。如果未做出此假设,则SQL Server将必须对每个函数调用执行详细检查(因为未绑定的函数可以随时更改)。

五个重要的函数属性:

  • 决定论
  • 精确
  • 资料存取
  • 系统数据访问
  • 系统验证

例如,采用以下未绑定标量函数:

CREATE FUNCTION dbo.F
(
    @i integer
)
RETURNS datetime
AS
BEGIN
    RETURN '19000101';
END;

我们可以使用元数据函数查看这五个属性:

SELECT 
    IsDeterministic = OBJECTPROPERTYEX(Func.ID, 'IsDeterministic'),
    IsPrecise = OBJECTPROPERTYEX(Func.ID, 'IsPrecise'),
    IsSystemVerified = OBJECTPROPERTYEX(Func.ID, 'IsSystemVerified'),
    UserDataAccess = OBJECTPROPERTYEX(Func.ID, 'UserDataAccess'),
    SystemDataAccess = OBJECTPROPERTYEX(Func.ID, 'SystemDataAccess')
FROM (VALUES(OBJECT_ID(N'dbo.F', N'FN'))) AS Func (ID);

结果

两个数据访问属性已设置为true,其他三个属性设置为false

这具有超出预期范围的含义(例如,在索引视图或索引计算列中使用)。

对查询优化器的影响

确定性特别属性会影响查询优化器。它具有有关允许执行的重写和操作类型的详细规则,并且这些规则对于非确定性元素非常受限制。副作用可能非常微妙。

例如,考虑以下两个表:

CREATE TABLE dbo.T1
(
    SomeInteger integer PRIMARY KEY
);
GO
CREATE TABLE dbo.T2
(
    SomeDate datetime PRIMARY KEY
);

...以及使用该函数(如先前定义)的查询:

SELECT * 
FROM dbo.T1 AS T1
JOIN dbo.T2 AS T2
    ON T2.SomeDate = dbo.F(T1.SomeInteger);

查询计划符合预期,其中包括对表T2的查找:

寻求计划

但是,如果使用派生表或公共表表达式编写相同的逻辑查询,则:

WITH CTE AS
(
    SELECT *, dt = dbo.F(T1.SomeInteger) 
    FROM dbo.T1 AS T1
)
SELECT * 
FROM CTE
JOIN dbo.T2 AS T2
    ON T2.SomeDate = CTE.dt;

-- Derived table
SELECT
    *
FROM 
(
    SELECT *, dt = dbo.F(T1.SomeInteger)
    FROM dbo.T1 AS T1
) AS T1
JOIN dbo.T2 AS T2
    ON T2.SomeDate = T1.dt;

执行计划现在具有扫描功能,谓词涉及卡在过滤器中的功能:

扫描计划

如果派生表或公用表表达式被视图或内联函数替换,也会发生这种情况。一个FORCESEEK提示(以及其他类似的尝试)将不会成功:

错误信息

根本问题是查询优化器无法自由地对不确定性查询元素进行重新排序

为了产生搜索,需要将Filter谓词从计划下移至T2数据访问。当功能不确定时,可以防止这种运动。

固定

此示例的修复包括两个步骤:

  1. WITH SCHEMABINDING
  2. 使功能确定

第一步很简单。第二个步骤涉及从字符串to删除不确定的隐式强制转换datetime。用确定性代替它CONVERT单靠这两个都不是足够的

ALTER FUNCTION dbo.F
(
    @i integer
)
RETURNS datetime
WITH SCHEMABINDING
AS
BEGIN
    -- Convert with a deterministic style
    RETURN CONVERT(datetime, '19000101', 112);
END;

现在,函数属性为:

新属性

释放优化器后,所有示例现在都可以生成所需的搜索计划


请注意,在函数中使用CASTto datetime将不起作用,因为无法使用该语法指定转换样式:

ALTER FUNCTION dbo.F
(
    @i integer
)
RETURNS datetime
WITH SCHEMABINDING
AS
BEGIN
    -- Convert with a deterministic style
    RETURN CAST('19000101' AS datetime);
END;

此函数定义产生扫描计划,并且属性显示它仍然不确定:

CAST函数属性

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.