【问题标题】:New cardinality estimator (SQL Server 2014) is way off新的基数估计器 (SQL Server 2014) 离我们还很遥远
【发布时间】:2014-12-19 03:47:24
【问题描述】:

我有一个数据仓库数据库,但我在使用 SQL Server 2014 的新基数估计器时遇到问题。

将数据库服务器升级到 SQL Server 2014 后,我观察到查询性能有很大差异。一些查询的执行速度要慢得多(SQL 2012 为 30 秒,而 SQL 2014 为 5 分钟)。 在研究了执行计划后,我发现 SQL Server 2014 上的基数估计值很差,我找不到原因。

以下是 SQL 2012 与 SQL 2014 中查询执行计划(左上角运算符)的示例:

一些细节:

  • 我的查询是典型的数据仓库事实表加载查询。我查询一个事务表并加入很多 (15-20) 个维度表(总是有 0 或 1 条记录从维度表中加入)。

  • 我已更新所有表的统计信息(使用 FULLSCAN)以确保统计信息是最新的。

  • 对维度表的业务键进行索引(唯一非聚集索引)。在我看来,由于这个索引的唯一性,旧的基数估计器(SQL 2012)正确地假设有最大值。 1 条连接的记录(估计的记录数在执行计划中没有变化)。

我试图将问题缩小到最简单的示例 - SELECT with 2 joins:

以下是 SQL 2012 与 SQL 2014 中运算符 1 和 2 的基数估计:

           | Est.rows - SQL2012 | Est.rows - SQL2014
Operator 1 |               7653 |               7653
Operator 2 |               7653 |              10000

如您所见,SQL Server 2014 未达到估计值 30% 以上(10000 对 7653)。因为我有cca。一个典型的查询有 15 到 20 个连接,最终的估计值相差甚远。

我可以将数据库置于较低的兼容模式 (110),然后它工作正常(与 SQL Server 2012 上相同),但我真的很想知道这种行为的原因是什么。为什么 SQL Server 2014 的基数估计结果错误?

【问题讨论】:

标签: sql-server sql-server-2014 cardinality-estimation


【解决方案1】:

我认为今天这个有趣的问题没有简单的答案。我知道的最佳答案是以下视频:http://channel9.msdn.com/events/TechEd/NorthAmerica/2014/DBI-B331#fbid=。它有许多新旧估算器的示例。视频时长约 50 多分钟,但值得花时间。

与此问题相关的视频摘要:

基数估计的旧假设:

  1. 一致性 - 数据是均匀分布的。
  2. 独立性 - 第 1 列与第 2 列无关。
  3. 遏制 - 当两个属性可能相同时,它们被假定为相同。
  4. 包含 - 应该有一个匹配项。

要在 SQL SERVER 2014 中使用 SQL SERVER 2012 基数估计器,请使用以下选项:

  • 选项 (querytraceon 9481) --revert to 2012

新的估算器在做什么(基于视频):

  • SQL Server 在索引和估计中使用平均选择性 行数乘以键的密度与总数 索引中的行。
  • 新的估计器不能很好地处理锯齿状分布。
  • 估计器之间的大多数差异都基于 WHERE 子句。
  • 新的基数估计器认为表之间存在相关性。
  • 您可以创建过滤统计信息来改进查询。 (http://msdn.microsoft.com/en-us/library/ms188038.aspx)

待办事项/清单:

1. Auto Create / Update Stats
2.  Check database compatibility mode (120/110)
3.  Test using query trace flags
4.  XML showplan

更新 基数估计器的新增功能 (SQL Server 2016)

  1. 越准确。
  2. CE 预测您的查询可能返回的行数
  3. SQL Server 2016 查询存储
  4. 跟踪 CE 基数预测的另一个选项是使用名为 query_optimizer_estimate_cardinality 的扩展事件
  5. CE 了解最大值可能高于上次收集统计数据时的值
  6. CE 了解同一表上的过滤谓词通常是相关的
  7. CE 不再假定来自不同表的过滤谓词之间存在任何关联

更多细节:

https://docs.microsoft.com/en-us/sql/relational-databases/performance/cardinality-estimation-sql-server

https://www.sqlshack.com/query-optimizer-changes-in-sql-server-2016-explained/

【讨论】:

    【解决方案2】:

    我想知道您是否在多列选择性估计方面遇到了这个问题:

    http://www.sqlskills.com/blogs/kimberly/multi-column-statistics-exponential-backoff/

    新的 CE 似乎仍有一些怪癖,也尝试使用 TF 4137,看看是否有帮助。

    最后确保您在最新的 CU 上并使用 TF 4199 运行以全面启用所有查询优化器修复,尽可能先在非生产环境中进行测试,并在全局启用设置时注意其他查询中的回归

    【讨论】:

    • 同意,这看起来像是新行政长官略微高估(因为它倾向于这样做)的情况。按照乔的帖子中的步骤进行调试将是一个很好的第一步。此外,当属性/谓词之间没有相关性时,旧版 CE 会更好地工作,这似乎也是这种情况。新的指数退避算法将倾向于高于传统 CE。
    【解决方案3】:

    这不是对这个问题的直接答案,但它可能会帮助那些面临与与基数估计器 (CE) 更改有关的 SCCM(又名 ConfigMgr)数据库相关的类似性能问题的人。由于 SQL Server 2014 和 SQL Server 2016 中新的基数估计器 (CE) 更改,SQL 查询可能会超时或您的 ConfigMgr 控制台运行缓慢。Microsoft 已针对此问题提供了解决方案here,建议应用适当的 SQL 基数估计器(CE)兼容等级如下表:

    SQL Server version    Supported compatibility       Recommended compatibility   
                          level values                  level for ConfigMgr
    
    SQL Server 2016       130, 120, 110, 100            130 
    
    SQL Server 2014       120, 110, 100                 110
    

    希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 2015-11-15
      • 1970-01-01
      • 2023-04-11
      • 1970-01-01
      • 1970-01-01
      • 2012-09-04
      • 1970-01-01
      • 1970-01-01
      • 2019-03-21
      相关资源
      最近更新 更多