基数估计逻辑(称为基数估算器)在 SQL Server 2014 中重新设计,以提高查询计划的质量,因此可以提高查询性能。 新的基数估算器包含适用于新式 OLTP 和数据仓库工作负载的假设和算法。 它基于对现代工作负荷的深入基数估算研究,以及过去 15 年改进 SQL Server 基数估算器的学习。 客户的反馈表明,虽然大多数查询将受益于更改或保持不变,但与以前的基数估算器相比,少量查询可能会显示回归。
注释
基数估计是查询结果中行数的预测。 查询优化器使用这些估计来选择用于执行查询的计划。 查询计划的质量直接影响到提高查询性能。
性能测试和优化建议
为 SQL Server 2014 中创建的所有新数据库启用新的基数估算器。 但是,升级到 SQL Server 2014 不会对现有数据库启用新的基数估算器。
要确保最佳查询性能,请使用以下建议在生产系统上启用新的基数估算器之前,测试您的工作负荷。
升级所有现有数据库以使用新的基数估算器。 为此,请使用 ALTER DATABASE 兼容性级别(Transact-SQL) 将数据库兼容性级别设置为 120。
使用新的基数估算器运行测试工作负荷,然后以当前排查性能问题的方式排查任何新的性能问题。
当您的工作负载在使用新的基数估算器(数据库兼容性级别 120 (SQL Server 2014))运行时,如果某个特定查询性能下降,您可以使用跟踪标志 9481 来运行该查询,以使用 SQL Server 2012 及更早版本中使用的基数估算器。 若要使用跟踪标志运行查询,请参阅知识库文章 “启用影响计划的 SQL Server 查询优化器行为”,这些行为可由特定查询级别的不同跟踪标志控制。
如果不能一次性更改所有数据库以使用新的基数估算器,则可以使用 ALTER DATABASE 兼容级别(Transact-SQL) 为所有数据库使用以前的基数估算器,将数据库兼容性级别设置为 110。
如果工作负荷以数据库兼容性级别 110 运行,并且想要使用新的基数估算器测试或运行特定查询,则可以使用跟踪标志 2312 运行查询,以使用基数估算器的 SQL Server 2014 版本。 若要使用跟踪标志运行查询,请参阅知识库文章 “启用影响计划的 SQL Server 查询优化器行为”,这些行为可由特定查询级别的不同跟踪标志控制。
新的 XEvents
有两个新的query_optimizer_estimate_cardinality XEvent 来支持新的查询计划。
query_optimizer_estimate_cardinality 当查询优化器估计关系表达式的基数时发生。
query_optimizer_force_both_cardinality_estimation_behaviors同时启用跟踪标志 2312 和 9481 时,尝试同时强制执行旧基数估计行为。
例子
以下示例显示了新基数估计中的一些更改。 已重写用于估算基数的代码。 逻辑很复杂,无法提供所有更改的详尽列表。
注释
这些示例以概念信息的形式提供。 您无需采取任何行动即可继续按照原有方式设计数据库和查询。
示例 A:新的基数估计使用了对最近添加的升序数据的平均基数。
此示例演示了新的基数估算器如何改进对在最近统计信息更新期间超出表中最大值的上升顺序数据进行的基数估计。
SELECT item, category, amount FROM dbo.Sales AS s WHERE Date = '2013-12-19';
在此示例中,每天将新行添加到 Sales 表中,查询会请求在 2013 年 12 月 19 日发生的销售额,统计信息上次更新为 2013/12/18。 以前的基数估算器假定自日期超过最大日期以来不存在 12/19/2013 值,并且统计信息尚未更新以包含 2013/12/19/2013 值。 如果在一天中加载数据,然后对数据运行查询,则在更新统计信息之前,会出现这种情况(称为升序关键问题)。
此行为已更改。 现在,尽管自上次统计更新以来添加的最新升序数据未被反映,新基数估算器仍假定这些值存在,并使用列中每个值的平均基数作为基数估计。
示例 B.新的基数估计假定同一表中筛选的谓词具有一些相关性
对于本示例,假设表“汽车”为 1000 行,Make 有 200 个“本田”的匹配项,模型有 50 个“Civic”匹配项,所有 Civics 都是本田。 因此,Make 列中的 20 个% 值为“本田”,模型列中的 5 个% 值为“Civic”,而本田 Civics 的实际数量为 50。 前面的基数估计假定 Make 和 Model 列中的值彼此独立。 前面的查询优化器估计有 10 个本田思域(.05 * .20 * 1000 行记录 = 10 行记录)。
SELECT year, purchase_price FROM dbo.Cars WHERE Make = 'Honda' AND Model = 'Civic';
此行为已更改。 现在,新的基数估计假定 Make 和 Model 列具有 一些 关联。 查询优化器通过将指数分量添加到估计公式来估计更高的基数。 查询优化器现在估计,22.36 行(.05 * SQRT(.20) * 1000 行 = 22.36 行)与谓词匹配。 对于此方案和特定数据分布,22.36 行更接近查询将返回的实际 50 行。
请注意,新的基数估算器逻辑对谓词选择性进行排序,并增加指数。 例如,如果谓词选择性为 .05、.20 和 .25,则基数估计为 (.05 * SQRT(.20) * SQRT(.25))。
示例 C.新的基数估计假定不同表中筛选的谓词是独立的
对于此示例,前面的基数估算器假定谓词筛选器 s.type 和 r.date 相关。 但是,现代工作负载的测试结果显示,不同表中的列上的谓词过滤器通常不相互关联。
SELECT s.ticket, s.customer, r.store FROM dbo.Sales AS s CROSS JOIN dbo.Returns AS r
WHERE s.ticket = r.ticket AND s.type = 'toy' AND r.date = '2013-12-19';
此行为已更改。 现在,新的基数估算器逻辑假定 s.type 与 r.date 无关。 实际上,假设玩具每天都归还,而不仅仅是在特定日期归还。 在这种情况下,新的基数估计数将小于以前的基数估计。