这个问题让我发疯了几天,我可能已经找到了答案,但我需要确认并检查最终的简单解决方案。
当存储过程使用一些用户定义的函数时,UDF 计划是否合并到主计划中并且一切都得到优化,还是每次都直接调用?
假设它没有发生,有没有办法强制 SQL Server 为特定的 SP 做这件事?
这个问题让我发疯了几天,我可能已经找到了答案,但我需要确认并检查最终的简单解决方案。
当存储过程使用一些用户定义的函数时,UDF 计划是否合并到主计划中并且一切都得到优化,还是每次都直接调用?
假设它没有发生,有没有办法强制 SQL Server 为特定的 SP 做这件事?
我在 SQL Server 中创建了一个物化视图,但是从中选择时,我得到的性能和执行计划与从未“物化”的相同查询中选择时相同。
观点很简单:
CREATE VIEW TestView WITH SCHEMABINDING
AS
SELECT TAB_A.C1, TAB_A.C2, TAB_A.C3
FROM TAB1
INNER JOIN TAB2 ON TAB1.C2 = TAB2.C2
INNER JOIN TAB3 ON TAB2.C1 = TAB3.C1;
CREATE UNIQUE CLUSTERED INDEX IX_TestView
ON TestView(C1, C2, C3);
现在,当我做类似的事情时
SELECT C1 FROM TestView
我希望在计划中看到只有对视图的访问,而不是其他任何东西,而是它访问基础表,就像视图甚至不存在一样。我也得到了完全相同的计划和相同的执行时间。
我究竟做错了什么?如果 SQL Server 无法“具体化”视图,我希望至少在创建它时会出现错误。
好吧,老实说,我找不到更好的标题了。
我最近来到了一个新的工作场所,有人要求我帮助处理数据库。我想尝试解释一个概念,但我不确定如何最好地表达它,也许这个概念已经有了更好的解释和名称。我不把自己标榜为 DB 专家,所以我想向他们展示一些比我自己的观点更正式的东西,无论我一生中设计了多少好的 DB。
我发现最有趣的一件事(但不是很好)是他们似乎是根据问题的逻辑而不是根据“这是一个数据库,它应该包含数据”来设计数据库,因此,例如要知道某个元素是否属于某个类别,查询将以这种方式进行(伪代码):
SELECT Column1, Column2...ColumnN
FROM Invoices [LIST OF JOIN]
WHERE
Invoces.Field1 IN
(TableA WHERE TableA.Field NOT IN
(TableB WHERE TableB.Field IN ((TableC WHERE) OR (TableD WHERE)))
OR Invoces.Field1 NOT IN
(TableB WHERE TableB.Field IN ((TableC WHERE) AND (TableD WHERE))
OR TableB.Field IN
(TableC WHERE TableC.Field IN (TableC WHERE))
OR TableB.Field NOT IN
(TableC WHERE TableC.Field NOT IN (TableD WHERE))
依此类推其他二十个左右的条件。不,我不是在开玩笑。
发生这种情况是因为他们没有说“这是一张发票,它的类别是发票本身的一个属性”,而是一直说“这张发票是由那个用户在那天插入的,他本可以插入它进入某个部门或根本没有,如果是部门,那么该部门可能是某个结构的一部分……”等等。这甚至不是参照完整性的问题,在这种情况下根本没有 FKs ...
另一个实际示例是文档的最后编辑日期:它不是作为属性存储,而是通过一个函数计算得出,该函数按照以下方式进行:
如果那个文档与另一个文档相关,那么如果另一个文档是这种,那么如果第一个文档也与这个其他文档相关,那么最后编辑的日期就是管理员打印每日约会日历的日期”。 .
显然,每个 if 也有一堆其他的。而且,这不是因为存在某种依赖关系,只是因为存储了很多东西来反映它们的逻辑。
在某种程度上,我很想说“一次写入,多次读取”,意思是“一次写入该属性,然后根据需要多次免费读取它”,因为我们的写入频率很低,并且读取频率非常高,显然所有读取都必须每次都重新计算所有内容。但我有一种感觉,一定有一些原则表明你应该设计数据库来保存数据......
我一直在到处寻找,但我找不到任何关于它的东西,似乎每个人都只关心 WHERE 和 CASE。(而且我手头没有 SQL Server 自己来验证它)
所以,一个简单的问题:SQL Server 是否基于 JOIN 条件短路 JOIN?如果我写:
TableA LEFT OUTER JOIN TableB ON 1=0 AND TableA.ID = TableB.A_ID
SQL Server 会完全跳过连接吗?
编辑
好的,有人正确地指出,这是在编译时解决的,所以我最好扩展这个问题。
以上只是作为一个例子,但结果证明是一个糟糕的例子。我想知道的是,当这种情况在运行时发生时,SQL Server 是否会使 JOIN 短路,作为传递给存储过程的@parameter 的结果。
我之所以问,是因为我肯定在过去几年中使用过类似的东西,但在与一些同事谈论它之前,我想 100% 确定。那么,SQL Server 是否会将其短路,然后:
TableA LEFT OUTER JOIN TableB ON @parameter IS NOT NULL AND TableA.ID = TableB.A_ID
如果它在 SP 内并且在 @parameter 设置为 NULL 的情况下调用它?如果存储过程是 WITH RECOMPILE,它会有什么不同吗?