【发布时间】: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