我有几个数据库,每个数据库都有一个名为products
的表。
其中一个数据库(“主”)包含应该从所有数据库中看到的产品。
我通过allproducts
视图执行此操作,如下所示:
CREATE VIEW allproducts AS
SELECT col[...] FROM products
UNION ALL SELECT col[...] FROM master.dbo.products;
这很有效,除了master数据库的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
的整个右侧?
如果对DB_NAME()
的每一行评估master.dbo.products
,是否有更简洁的方法来执行此操作,还是必须维护单独的视图定义?
更新:“所有元数据函数都是不确定的。这意味着这些函数在每次调用时都不会返回相同的结果,即使使用相同的输入值集也是如此。” - http://msdn.microsoft.com/en-us/library/ms187812.aspx
我发现另一个问题,其中有人有类似的情况,并找到了合理的解决方法:
因此,问题的主要部分已得到解答。尽管DB_NAME()是不确定的,但执行计划与调用确定性UDF相同而不是调用DB_NAME(),而性能表明DB_NAME()结果 会缩短其他分支。查询。它们都不像WHERE子句中的标量比较(如“0 = 1”)那么快,因此即使是确定性函数也不能完全优化计划。我可以和UDF一起生活,所以我会为这种情况走这个方向。
答案 0 :(得分:0)
我强烈建议不要依赖SQL Server短路,即使在你已经验证它现在可用,当前版本,当前数据,当前硬件等情况下也是如此。这是SQL的唯一地方服务器保证短路AFAIK位于CASE
表达式内。即使在那里,优化器也有更重要的规则要遵循(例如,使用聚合时短路可能会中断)。
你真的认为你的主要优化问题是,每行是否评估DB_NAME()
?我相当肯定它不会,但如果这是杀死你表现的稻草,那么肯定有更重要的问题需要解决。
答案 1 :(得分:0)
“所有元数据函数都是不确定的。这意味着这些函数在每次调用时都不会返回相同的结果,即使使用相同的输入值集也是如此。” - http://msdn.microsoft.com/en-us/library/ms187812.aspx
我最终没有打开DB_NAME(),只维护每个DDL的两个版本。令人讨厌,但即使UDF返回一个恒定的比特值也不如我希望的那么高效。