新基数估算器中的联接包含假设会降低查询性能
本文可帮助解决使用新基数估算器编译查询时 SQL Server 2014 及更高版本中可能发生的性能问题。
原始产品版本:SQL Server
原始 KB 数: 3189675
现象
假设出现了下面这种情景:
- 你使用的是 SQL Server 2014 或更高版本。
- 运行包含联接和非联接筛选器谓词的查询。
- 使用新的 基数估计(SQL Server)(新 CE) 编译查询。
在此方案中,你将体验查询性能下降。
如果使用旧版 CE 编译查询,则不会出现此问题。
原因
从 SQL Server 2014 中,为数据库兼容性级别 120 及更高版本引入了新的基数估算器(新 CE)。 当查询优化器估计不同运算符和谓词的基数时,新 CE 会更改模型中旧 CE 的几个假设。
其中一项更改与联接包含假设相关。
旧版 CE 模型假定用户始终查询存在的数据。 这意味着,对于涉及两个表的等联接运算的联接谓词,联接列存在于联接的两侧。 在存在针对联接表的其他非联接筛选器谓词的情况下,旧版 CE 假定联接谓词和非联接筛选器谓词具有某种级别的关联。 这种隐含关联称为简单包含。
或者,新 CE 使用基本包含作为相关性。 新的 CE 模型假定用户可能会查询不存在的数据。 这意味着,单独的表上的筛选器谓词可能不相互关联。 因此,我们使用概率方法。
对于许多实际方案,使用基本包含假设可创建更好的估计值。 这反过来又会创建更高效的查询计划选择。 但是,在某些情况下,使用简单包含假设可能会提供更好的结果。 如果发生这种情况,使用新 CE 而不是旧版 CE 时,可能会遇到效率较低的查询计划选择。
有关如何排查与新 CE 相关的问题的详细信息,请参阅 从 SQL Server 2012 或更高版本升级到 2014 或更高版本后降低查询性能。
解决方法
在 SQL Server 2014 及更高版本中,可以使用 跟踪标志 9476 强制 SQL Server 使用简单包含假设,而不是默认的基本包含假设。 如果可以修改应用程序查询,更好的选择是在 SQL Server 2016 (13.x) SP1 之后使用查询提示 ASSUME_JOIN_PREDICATE_DEPENDS_ON_FILTERS
。 有关详细信息,请参阅 USE HINT。 例如:
SELECT * FROM Table1 t1
JOIN Table2 t2
ON t1.Col1 = t2.Col1
WHERE Col1 = 10
OPTION (USE HINT ('ASSUME_JOIN_PREDICATE_DEPENDS_ON_FILTERS'));
如果满足以下条件,则启用此跟踪标志或使用查询提示可以提高查询计划选择,而无需完全还原为旧 CE 模型:
- 对于包含联接和非联接筛选器谓词的查询,你将体验到一个欠佳的查询计划选择,这会导致整体性能下降。
- 可以在“联接基数”估计中验证重大不准确(即实际行数与估计的行数明显不同)。
- 使用旧 CE 编译查询时,此不准确之处不存在。
可以在会话级别或查询级别全局启用此跟踪标志。
注意
错误地使用跟踪标志可能会降低工作负荷性能。 有关详细信息,请参阅 提示 (Transact-SQL) - 查询。