DB_NAME()是一个确定性函数吗



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

其中一个数据库("master")包含的产品应在所有数据库中可见。

我通过以下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(),有没有更干净的方法可以做到这一点,或者我必须维护单独的视图定义?

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

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

  • 有什么方法可以使这个UDF具有确定性吗

因此,问题的主要部分已经得到了回答。尽管DB_NAME()是不确定性的,但调用确定性UDF和调用DB_NAME的执行计划是相同的,性能表明DB_NAME)结果确实缩短了查询的其他分支。两者都不如WHERE子句中的"0=1"之类的标量比较快,因此即使是确定性函数也不能完全优化计划。我可以使用UDF,所以在这种情况下,我将朝着这个方向发展。

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

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

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

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

最新更新