Tuyen Nguyen Asked: 2024-11-07 04:35:23 +0800 CST2024-11-07 04:35:23 +0800 CST 2024-11-07 04:35:23 +0800 CST 为什么我的嵌套循环连接在 SQL Server 中显示不准确的行估计? 772 我有以下执行计划: 如您所见,Clustered Index ScanandIndex Seek运算符的行估计是准确的。然而,嵌套循环连接存在显著差异:实际行数为 6,420,而估计行数只有 72。 我的问题是: 如何估算 SQL Server 中嵌套循环连接的行数? 在这种情况下,哪些因素可能导致行估计如此不准确? 我能做些什么来改善或修正这个估计吗? 感谢您的任何见解! sql-server 3 个回答 Voted Best Answer Paul White 2024-11-07T11:00:38+08:002024-11-07T11:00:38+08:00 如何估算 SQL Server 中嵌套循环连接的行数? 与哈希或合并连接没什么不同。SSMS 中的显示对于嵌套循环通常看起来不同,因为内侧是每次执行(查看预执行(估计)计划时)。 从根本上讲,您要问的是 SQL Server 如何估计连接的选择性。 无论选择哪种物理实现(嵌套循环、应用、哈希、合并),逻辑选择性都保持不变。 这个问题的广泛答案是,SQL Server 可能会使用基于直方图或频率(不同值)信息的几种技术之一作为连接谓词列。 对于基于直方图或频率的估计,没有单一的公式。根据所涉及的谓词、可用信息和数据库配置,可能会出现几种建模变体。 最重要的配置因素是您使用的基数估计 (CE) 模型(“默认”或“旧版”)、数据库兼容级别设置以及是否启用了查询优化器修补程序。这不是完整的列表。 这个问题在细节上特别少——甚至没有提供连接谓词——所以我甚至不会在这里推测具体的原因。 在这种情况下,哪些因素可能导致行估计如此不准确? 估算值是根据使用 SQL Server 专有建模假设和算法的统计信息计算得出的。鉴于代表性统计数据,估算值不准确的最常见原因是数据与 SQL Server 建模假设之间的脱节。 我能做些什么来改善或修正这个估计吗? 首先,确保统计数据是最新的且质量良好。不要仅仅依赖默认的抽样统计数据。您可能需要更高的抽样率,甚至FULLSCAN需要提供足够准确的信息。您可能还需要创建额外的统计数据或索引,具体取决于连接的确切性质。 一旦确定了这一点,您可以尝试以下主要操作: 使用不同的基数估计模型 FORCE_DEFAULT_CARDINALITY_ESTIMATION FORCE_LEGACY_CARDINALITY_ESTIMATION 使用记录的模型变化 ASSUME_JOIN_PREDICATE_DEPENDS_ON_FILTERS ASSUME_MIN_SELECTIVITY_FOR_FILTER_ESTIMATES ASSUME_FULL_INDEPENDENCE_FOR_FILTER_ESTIMATES ASSUME_PARTIAL_CORRELATION_FOR_FILTER_ESTIMATES 如果之前的估计值更好,则使用不同的优化器兼容级别 QUERY_OPTIMIZER_COMPATIBILITY_LEVEL_n 以上选项均指定为USE HINT查询提示。 资源 现有问答:嵌套循环运算符使用什么方法/公式进行行估计? 如果您真的对底层连接选择性过程或如何组合多个谓词感兴趣: 使用 SQL Server 2014 基数估算器优化查询计划- Microsoft 加入由 Dmitry Piliugin 撰写的Estimation Internals 使用直方图粗对齐进行连接基数估计 我进行的多个谓词的基数估计 我进行的析取 (OR) 谓词基数估计 mustaccio 2024-11-07T05:22:37+08:002024-11-07T05:22:37+08:00 SQL Server 维护列基数和值分布直方图的统计信息,因此它能够以一定程度的准确性估计有多少行可能与单个表的一列或一组列的特定谓词相匹配。但是,它不知道一列中有多少值可能与另一个表的列中的某个值相匹配,即它没有列相关性统计信息。 生成和使用此类统计数据的一种可能机制是允许在普通(非物化且非索引)视图上收集统计数据。然后,您将创建一个连接两个(或更多)表的视图,引擎将计算相关列值的直方图。 SQL Server 似乎没有能力维护常规视图的统计数据,但它允许您生成索引视图的统计数据,人们希望这会产生类似的效果,所以您可以尝试一下。当然,维护相应的物理索引会降低性能,还会占用额外的存储空间。 David Browne - Microsoft 2024-11-07T05:32:33+08:002024-11-07T05:32:33+08:00 对于嵌套循环运算符,“估计”是外部表中每行的数据,即每个“循环”,而“实际”是所有循环的总和。 例如参见:https ://kendralittle.com/2016/09/06/estimated-vs-actual-number-of-rows-in-nested-loop-operators/
与哈希或合并连接没什么不同。SSMS 中的显示对于嵌套循环通常看起来不同,因为内侧是每次执行(查看预执行(估计)计划时)。
从根本上讲,您要问的是 SQL Server 如何估计连接的选择性。 无论选择哪种物理实现(嵌套循环、应用、哈希、合并),逻辑选择性都保持不变。
这个问题的广泛答案是,SQL Server 可能会使用基于直方图或频率(不同值)信息的几种技术之一作为连接谓词列。
对于基于直方图或频率的估计,没有单一的公式。根据所涉及的谓词、可用信息和数据库配置,可能会出现几种建模变体。
最重要的配置因素是您使用的基数估计 (CE) 模型(“默认”或“旧版”)、数据库兼容级别设置以及是否启用了查询优化器修补程序。这不是完整的列表。
这个问题在细节上特别少——甚至没有提供连接谓词——所以我甚至不会在这里推测具体的原因。
估算值是根据使用 SQL Server 专有建模假设和算法的统计信息计算得出的。鉴于代表性统计数据,估算值不准确的最常见原因是数据与 SQL Server 建模假设之间的脱节。
首先,确保统计数据是最新的且质量良好。不要仅仅依赖默认的抽样统计数据。您可能需要更高的抽样率,甚至
FULLSCAN
需要提供足够准确的信息。您可能还需要创建额外的统计数据或索引,具体取决于连接的确切性质。一旦确定了这一点,您可以尝试以下主要操作:
使用不同的基数估计模型
使用记录的模型变化
如果之前的估计值更好,则使用不同的优化器兼容级别
以上选项均指定为
USE HINT
查询提示。资源
如果您真的对底层连接选择性过程或如何组合多个谓词感兴趣:
SQL Server 维护列基数和值分布直方图的统计信息,因此它能够以一定程度的准确性估计有多少行可能与单个表的一列或一组列的特定谓词相匹配。但是,它不知道一列中有多少值可能与另一个表的列中的某个值相匹配,即它没有列相关性统计信息。
生成和使用此类统计数据的一种可能机制是允许在普通(非物化且非索引)视图上收集统计数据。然后,您将创建一个连接两个(或更多)表的视图,引擎将计算相关列值的直方图。
SQL Server 似乎没有能力维护常规视图的统计数据,但它允许您生成索引视图的统计数据,人们希望这会产生类似的效果,所以您可以尝试一下。当然,维护相应的物理索引会降低性能,还会占用额外的存储空间。
对于嵌套循环运算符,“估计”是外部表中每行的数据,即每个“循环”,而“实际”是所有循环的总和。
例如参见:https ://kendralittle.com/2016/09/06/estimated-vs-actual-number-of-rows-in-nested-loop-operators/