【问题标题】:Is DB_NAME() a deterministic function?DB_NAME() 是确定性函数吗?
【发布时间】:2012-03-08 15:11:37
【问题描述】:

我有几个数据库,每个数据库都有一个名为 products 的表。

其中一个数据库(“主数据库”)包含应该在所有数据库中可见的产品。

我通过allproducts 视图来做到这一点,如下所示:

CREATE VIEW allproducts AS
   SELECT col[...] FROM products
   UNION ALL SELECT col[...] FROM master.dbo.products;

这很好用,只是主数据库的allproducts 视图需要一个自带产品的定义:

CREATE VIEW allproducts AS
   SELECT col[...] FROM products;

为了简化一点,我想要一个通用的视图定义,如下所示:

CREATE VIEW allproducts AS
   SELECT col[...] FROM products
   UNION ALL SELECT col[...] FROM master.dbo.products
     WHERE (DB_NAME() <> 'master');

工作,但我担心性能。那么,DB_NAME() 函数是否具有确定性,如果是,SQL Server 是否会根据比较缩短整个 UNION ALL 右侧?

如果为master.dbo.products 的每一行评估DB_NAME(),是否有更简洁的方法来执行此操作,或者我必须维护单独的视图定义?

更新:“所有元数据函数都是不确定的。这意味着这些函数在每次调用时并不总是返回相同的结果,即使使用相同的输入值集也是如此。” - http://msdn.microsoft.com/en-us/library/ms187812.aspx

我发现了另一个问题,有人遇到类似情况并找到了合理的解决方法:

所以问题的主要部分已经回答了。尽管 DB_NAME() 是非确定性的,但调用确定性 UDF 与调用 DB_NAME() 的执行计划是相同的,并且性能表明 DB_NAME() 结果确实缩短了询问。两者都没有像 WHERE 子句中的“0 = 1”这样的标量比较那么快,因此即使是确定性函数也不能完全优化计划。我可以忍受 UDF,所以我会在这种情况下朝那个方向发展。

【问题讨论】:

  • 从您的问题中不清楚您是否真的有问题。首先,您“关心”性能,但是您是否有可观察到的性能问题?如果是这样,首先要查看的是查询的执行计划。其次,您想要一种“更清洁”的方式来做到这一点,那么部署或代码管理是否存在问题?如果是这样,您无法自动化或编写此配置的哪一部分?您可能还希望将同义词视为简化代码的一种方式,但您没有提及您的 SQL Server 版本,因此您可能无法使用它们。
  • 答案应该是主观的——SQL Server 是否足够聪明,可以像我希望的那样走捷径,或者不能。我还没有可观察到的性能问题,因为我还没有在生产中使用它。这些视图比提供的示例要复杂一些,所以我宁愿不花时间这样做,然后然后发现我在逻辑上犯了一个严重的错误。我通常会在自动化方面与您同在,但这在这里行不通。代码管理是长期问题,而不是部署问题——我宁愿不维护每个视图的两个版本。同义词不会合并表格。

标签: sql-server performance tsql


【解决方案1】:

我强烈建议不要依赖 SQL Server 短路,即使在您已经验证它在今天、在当前版本、当前数据、当前硬件等情况下也可以工作。SQL Server 短路的唯一地方服务器保证短路,AFAIK,在 CASE 表达式内。即使在那里,优化器也有更重要的规则要遵循(例如,使用聚合时短路可能会中断)。

您真的认为您的主要优化问题是是否对每一行都评估DB_NAME()?我相当肯定它不会,但如果这是扼杀你表现的稻草,那么肯定还有更重要的问题需要解决。

【讨论】:

    【解决方案2】:

    “所有元数据函数都是不确定的。这意味着这些函数在每次调用时并不总是返回相同的结果,即使使用相同的输入值集也是如此。” - http://msdn.microsoft.com/en-us/library/ms187812.aspx

    我最终没有打开 DB_NAME() 而是只维护每个 DDL 的两个版本。烦人,但即使是返回恒定位值的 UDF 也没有我希望的那么高效。

    【讨论】:

      猜你喜欢
      • 2013-12-13
      • 1970-01-01
      • 2011-12-31
      • 2012-05-13
      • 2016-10-20
      • 1970-01-01
      • 1970-01-01
      • 2022-01-17
      相关资源
      最近更新 更多