Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 估计的子树成本大幅度降低,优化效果糟糕_Sql_Sql Server_Tsql_Sql Server 2008 - Fatal编程技术网

Sql 估计的子树成本大幅度降低,优化效果糟糕

Sql 估计的子树成本大幅度降低,优化效果糟糕,sql,sql-server,tsql,sql-server-2008,Sql,Sql Server,Tsql,Sql Server 2008,我将一个有两个记录id字段(record1,record2)的表连接到一个视图两次——每个记录一次——并选择前1000个。视图由几个相当大的表组成,它的id字段是它们各自id的字符串连接(这对于某些需要视图唯一id的第三方软件是必要的。行编号非常慢)。视图中还有一个where子句调用比较日期的函数 除非我使用选项(强制顺序),否则估计的执行计划将生成“无连接谓词”警告。通过强制订购,执行计划有多个节点显示100%的成本。在这两种情况下,端点处估计的子树开销比它的一个节点小十三个数量级(它正在进行

我将一个有两个记录id字段(record1,record2)的表连接到一个视图两次——每个记录一次——并选择前1000个。视图由几个相当大的表组成,它的id字段是它们各自id的字符串连接(这对于某些需要视图唯一id的第三方软件是必要的。行编号非常慢)。视图中还有一个where子句调用比较日期的函数

除非我使用选项(强制顺序),否则估计的执行计划将生成“无连接谓词”警告。通过强制订购,执行计划有多个节点显示100%的成本。在这两种情况下,端点处估计的子树开销比它的一个节点小十三个数量级(它正在进行大量或嵌套的循环联接,cpu开销高达35927400000000)

执行计划中的数字是怎么回事?为什么SQL Server很难优化查询

只需在连接字符串的视图中添加一个索引,并使用NOEXPAND表提示即可完全解决此问题。它总共运行了12秒钟。但是为什么sql会如此糟糕(甚至在我添加索引后需要noexpand提示)

使用CU 8运行SQL Server 2008 SP1

视图:

SELECT
    dbo.fnGetCombinedTwoPartKey(N.NameID,A.AddressID) AS NameAddressKey,
    [other fields]

FROM     
    [7 joined tables]
WHERE dbo.fnDatesAreOverlapping(N.dtmValidStartDate,N.dtmValidEndDate,A.dtmValidStartDate,A.dtmValidEndDate) = 1
查询

SELECT TOP 1000
    vw1.strFullName,
    vw1.strAddress1,
    vw1.strCity,
    vw2.strFullName,
    vw2.strAddress1,
    vw2.strCity
FROM tblMatches M
JOIN vwImportNameAddress vw1 ON vw1.NameAddressKey = M.Record1 
JOIN vwImportNameAddress vw2 ON vw2.DetailAddressKey = M.Record2 

它必须解析您的函数(fngGetCombinedTwoPartKey),以确定获取哪些列来创建结果列。不可能,所以假设所有列都是必需的。如果你的指数覆盖了指数,那么你的估计就错了。

看起来你已经非常接近解释了。这是因为:

视图由几个相当大的表组成,它的id字段是它们各自id的字符串连接

这将创建一个不可搜索的连接谓词条件,并防止SQLServer使用基表上的任何索引。因此,引擎必须对每个联接的所有基础表执行完全扫描(在您的情况下为两个)

可能是为了避免进行几次完整的表扫描(每个表扫描一次,乘以连接数),SQL Server决定简单地使用笛卡尔乘积并在之后进行过滤会更快(因此出现“无连接谓词”警告)。当您强制订购时,它会尽职尽责地执行您最初要求的所有完整扫描和嵌套循环

我确实同意一些评论,即该视图是一个有问题的数据模型的基础,但正如您所发现的,短期的解决方法是在视图中索引computed ID列,这(显然)使其再次可搜索,因为它具有实际生成的ID的散列


编辑:我在第一次通读时也错过了这一点:

WHERE dbo.fnDatesAreOverlapping(N.dtmValidStartDate,N.dtmValidEndDate,A.dtmValidStartDate,A.dtmValidEndDate) = 1

这也是一个不可搜索的谓词,它将导致性能低下。在UDF中包装任何列都会导致此行为。对视图进行索引也会使其具体化,这也可能会影响查询的速度;如果没有索引,每次都必须对该谓词求值,并强制对基表进行完全扫描,即使没有复合ID。

您可以发布查询和视图定义吗?视图的使用听起来很可怕-请尝试支持表,但我真的认为您的数据模型需要进行更好的更改…视图对于需要为联接表提供唯一键的第三方应用程序是必需的。用结果填充一个保留表并将其传递给应用程序可能会更好,但我更感兴趣的是为什么sql在这里失败得很惨。是否使用了函数、多个大型联接等(我怀疑在串联的、字符串转换的ID上联接是必要的,因为表提示是必要的,但这并不能解释为什么估计的执行计划完全不一致)但我很好奇,sql server在没有noexpand提示的情况下无法正确利用索引的原因。看起来我应该在估算中记下错误的数字,因为sql无法在非常大的数据集上处理非常糟糕的查询。布莱恩:在没有相反证据的情况下,我可能会责怪过时的统计数据。如果必须使用
NOEXPAND
,那么这意味着优化器认为查询基表比使用视图上的索引更便宜;我能想到的唯一原因是:(a)更多的不可搜索谓词没有显示在最终的查询示例中,或者(b)优化器认为基表查询将比实际查询便宜得多(这通常是由于糟糕的统计数据)。如果您确定谓词是正确的,请尝试
sp\u updatestats
。哦,这也可能是非覆盖索引的结果。如果物化视图实际上没有所有必要的输出列,那么它必须有效地将视图连接到每个基表,这可能会被认为是非常昂贵的。确保您在索引中正确使用了
INCLUDE
。我认为我对保留UDF和依赖提示而不是替换为基础逻辑(随着必须重叠的日期范围数量的增加,这会变得非常冗长)的一般观点有很好的了解。。。