AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 140381
Accepted
Paul White
Paul White
Asked: 2016-06-04 22:35:05 +0800 CST2016-06-04 22:35:05 +0800 CST 2016-06-04 22:35:05 +0800 CST

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

  • 772

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

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

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

sql-server functions
  • 1 1 个回答
  • 10298 Views

1 个回答

  • Voted
  1. Best Answer
    Paul White
    2016-06-04T22:35:05+08:002016-06-04T22:35:05+08:00

    是的。

    未能指定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。

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

    对查询优化器的影响

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

    例如,考虑以下两个表:

    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尝试)不会成功:

    错误信息

    根本问题是查询优化器不能随意重新排序不确定的查询元素。

    为了产生一个搜索,过滤器谓词需要在计划中向下移动到 T2 数据访问。当函数是不确定的时,会阻止这种移动。

    使固定

    此示例的修复涉及两个步骤:

    1. 添加WITH SCHEMABINDING
    2. 使函数具有确定性

    第一步是微不足道的。第二个涉及从 string 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;
    

    函数属性现在是:

    新房源

    随着优化器的释放,所有示例现在都会生成所需的搜索计划。


    请注意,在函数中使用CASTtodatetime是行不通的,因为无法在该语法中指定转换样式:

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

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

    CAST 函数属性

    • 92

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve