内部联接的基数估计问题


13

我正在努力理解为什么行估计是如此严重的错误,这是我的情况:

简单连接-使用SQL Server 2016 sp2(在sp1上存在相同问题),dbcompatiblity = 130。

select Amount_TransactionCurrency_id, CurrencyShareds.id 
from CurrencyShareds 
    INNER JOIN annexes ON Amount_TransactionCurrency_id = CurrencyShareds.Id 
option (QUERYTRACEON 3604, QUERYTRACEON 2363);

SQL估计1行,而SQL为107131,并选择做一个嵌套循环(链接到plan)。在CurrencyShareds上更新统计信息之后,估算就可以了,并选择了合并联接(链接到新计划)。一旦仅将一条记录添加到CurrencyShareds,统计信息就会“过时”,并且sql返回错误的估计。

我不太担心这个简单的查询,但这只是一个更大的查询的一部分,而这就是多米诺骨牌的开始...

为什么在100条记录表中添加一行会造成这种损坏?查看基数估计跟踪的输出时,我看到此警告,***WARNING: badly-formed histogram ***但在此主题上找不到更多信息。

这是基数估计的全部输出:

Begin selectivity computation
Input tree:

LogOp_Join

CStCollBaseTable(ID=1, CARD=107131 TBL: annexes)

CStCollBaseTable(ID=2, CARD=100 TBL: CurrencyShareds)

ScaOp_Comp x_cmpEq

ScaOp_Identifier QCOL: [test.MasterData].[dbo].[CurrencyShareds].Id

ScaOp_Identifier QCOL: [test.MasterData].[dbo].[Annexes].Amount_TransactionCurrency_id

Plan for computation:

CSelCalcExpressionComparedToExpression( QCOL: [test.MasterData].[dbo].[Annexes].Amount_TransactionCurrency_id x_cmpEq QCOL: [test.MasterData].[dbo].[CurrencyShareds].Id )

Loaded histogram for column QCOL: [test.MasterData].[dbo].[Annexes].Amount_TransactionCurrency_id from stats with id 7

Loaded histogram for column QCOL: [test.MasterData].[dbo].[CurrencyShareds].Id from stats with id 1 *** WARNING: badly-formed histogram ***

Selectivity: 4.59503e-018

Stats collection generated:

CStCollJoin(ID=3, CARD=1 x_jtInner)

CStCollBaseTable(ID=1, CARD=107131 TBL: annexes)

CStCollBaseTable(ID=2, CARD=100 TBL: CurrencyShareds)

End selectivity computation

Estimating distinct count in utility function

Input stats collection:

CStCollBaseTable(ID=1, CARD=107131 TBL: annexes)

Columns to distinct on:QCOL: [test.MasterData].[dbo].[Annexes].Amount_TransactionCurrency_id

Plan for computation:

CDVCPlanLeaf

0 Multi-Column Stats, 1 Single-Column Stats, 0 Guesses

Covering multi-col stats id: 7

Using ambient cardinality 107131 to combine distinct counts:

5

Combined distinct count: 5

Result of computation: 5

Estimating distinct count in utility function

Input stats collection:

CStCollBaseTable(ID=2, CARD=100 TBL: CurrencyShareds)

Columns to distinct on:QCOL: [test.MasterData].[dbo].[CurrencyShareds].Id

Plan for computation:

CDVCPlanUniqueKey

Result of computation: 100

当我更新CurrencyShareds的统计信息时,“直方图格式错误”的部分会发生变化,并且基数可以正确计算

Plan for computation:

CSelCalcExpressionComparedToExpression( QCOL: [test.MasterData].[dbo].[Annexes].Amount_TransactionCurrency_id x_cmpEq QCOL: [test.MasterData].[dbo].[CurrencyShareds].Id )

Loaded histogram for column QCOL: [test.MasterData].[dbo].[Annexes].Amount_TransactionCurrency_id from stats with id 7

Loaded histogram for column QCOL: [test.MasterData].[dbo].[CurrencyShareds].Id from stats with id 1

Selectivity: 0.01

Stats collection generated:

CStCollJoin(ID=3, CARD=107131 x_jtInner)

CStCollBaseTable(ID=1, CARD=107131 TBL: annexes)

CStCollBaseTable(ID=2, CARD=100 TBL: CurrencyShareds)

End selectivity computation

以及有关“ [CurrencyShareds] .id来自ID为1的统计信息”的统计信息,并带有有关直方图的警告,这对我来说很好...

Name                                                                                                                             Updated              Rows                 Rows Sampled         Steps  Density       Average key length String Index Filter Expression                                                                                                                                                                                                                                                Unfiltered Rows      Persisted Sample Percent
-------------------------------------------------------------------------------------------------------------------------------- -------------------- -------------------- -------------------- ------ ------------- ------------------ ------------ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------- ------------------------
PK_CurrencyShareds_Id                                                                                                            May 23 2018 10:43PM  98                   98                   75     1             8                  NO           NULL                                                                                                                                                                                                                                                             98                   0

(1 row affected)

All density   Average Length Columns
------------- -------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
0,01020408    8              Id

(1 row affected)

RANGE_HI_KEY         RANGE_ROWS    EQ_ROWS       DISTINCT_RANGE_ROWS  AVG_RANGE_ROWS
-------------------- ------------- ------------- -------------------- --------------
119762190797406464   0             1             0                    1
119762190797406466   1             1             1                    1
119762190797406468   1             1             1                    1
119762190797406470   1             1             1                    1
119762190797406472   1             1             1                    1
119762190797406474   1             1             1                    1
119762190797406476   1             1             1                    1
119762190797406478   1             1             1                    1
119762190797406480   1             1             1                    1
119762190797406482   1             1             1                    1
119762190797406484   1             1             1                    1
119762190797406486   1             1             1                    1
119762190797406488   1             1             1                    1
119762190797406490   1             1             1                    1
119762190797406492   1             1             1                    1
119762190797406494   1             1             1                    1
119762190797406496   1             1             1                    1
119762190797406498   1             1             1                    1
119762190797406500   1             1             1                    1
119762190797406502   1             1             1                    1
119762190797406504   1             1             1                    1
119762190797406506   1             1             1                    1
119762190797406507   0             1             0                    1
478531702587687680   0             1             0                    1
478531702591881728   0             1             0                    1
478531702591881729   0             1             0                    1
478531702591881984   0             1             0                    1
478531702591881985   0             1             0                    1
478531702596076032   0             1             0                    1
478531702596076033   0             1             0                    1
478531702596076288   0             1             0                    1
478531702600270336   0             1             0                    1
478531702600270592   0             1             0                    1
478532235583062528   0             1             0                    1
478532235583062784   0             1             0                    1
478532235587256832   0             1             0                    1
530792464911467264   0             1             0                    1
530792464924049920   0             1             0                    1
530792464924050176   0             1             0                    1
530792464928244224   0             1             0                    1
530792464928244480   0             1             0                    1
530792464932438528   0             1             0                    1
530792464932438784   0             1             0                    1
530792464936632832   0             1             0                    1
530792464936632833   0             1             0                    1
530792464936633088   0             1             0                    1
530792464940827136   0             1             0                    1
530792464940827392   0             1             0                    1
530792464949216000   2             1             2                    1
530792464953410048   0             1             0                    1
530792464953410304   0             1             0                    1
530792464957604352   0             1             0                    1
530792464957604353   0             1             0                    1
530792464957604608   0             1             0                    1
530792464961798656   0             1             0                    1
530792464961798912   0             1             0                    1
530792464965992960   0             1             0                    1
530792464965993216   0             1             0                    1
530792464965993217   0             1             0                    1
530792464970187264   0             1             0                    1
530792464970187265   0             1             0                    1
530792464970187520   0             1             0                    1
530792464974381568   0             1             0                    1
530792464974381824   0             1             0                    1
530792464974381825   0             1             0                    1
530792464978575872   0             1             0                    1
530792464978575873   0             1             0                    1
530792464978576128   0             1             0                    1
867420708903354880   0             1             0                    1
867420708903355136   0             1             0                    1
867420708903355137   0             1             0                    1
960876568220042240   0             1             0                    1
976385263448130048   0             1             0                    1
977302121709864192   0             1             0                    1
977955748426318592   0             1             0                    1

和第二个索引的信息:

Name                                                                                                                             Updated              Rows                 Rows Sampled         Steps  Density       Average key length String Index Filter Expression                                                                                                                                                                                                                                                Unfiltered Rows      Persisted Sample Percent
-------------------------------------------------------------------------------------------------------------------------------- -------------------- -------------------- -------------------- ------ ------------- ------------------ ------------ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------- ------------------------
IX_FK_Amount_TransactionCurrency                                                                                                 May 21 2018  3:29PM  107204               107204               5      0             16                 NO           NULL                                                                                                                                                                                                                                                             107204               0

(1 row affected)

All density   Average Length Columns
------------- -------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
0,2           8              Amount_TransactionCurrency_id
9,32801E-06   16             Amount_TransactionCurrency_id, Id

(2 rows affected)

RANGE_HI_KEY         RANGE_ROWS    EQ_ROWS       DISTINCT_RANGE_ROWS  AVG_RANGE_ROWS
-------------------- ------------- ------------- -------------------- --------------
119762190797406475   0             160           0                    1
119762190797406478   0             867           0                    1
119762190797406481   0             106           0                    1
119762190797406494   0             105742        0                    1
119762190797406496   0             329           0                    1

Answers:


10

根据您的直方图,我能够在2017年CU6中重现该问题。我不会说你做错了。相反,基数估计出了点问题。这是插入行之前得到的:

在此处输入图片说明

插入行后,最终基数估计会下降很多:

在此处输入图片说明

您在这里有一个非常简单的复制程序,所以我的建议是提交产品反馈或与Microsoft打开支持通知单。我能够找到一些适用于您的样本数据的解决方法,其中一种可能对您而言是可以接受的。

  1. 将唯一索引放在上CurrencyShareds.Id。没有唯一索引,我无法使repro正常工作。该表很小,因此也许不用索引就可以解决。当然,您可能有很好的理由予以保留。
  2. 将联接的结果具体化到临时表中。根据您的问题,在此步骤中获得合理的估算很重要,这样较大的查询才能很好地执行。临时表是实现这一目标的一种方法。
  3. 使用旧版CE。我无法复制该问题。当然,这可能会对您的其余查询产生负面影响。
  4. 用愚蠢的代码欺骗查询优化器。例如,在我的测试中,以下重写非常有效:

select Amount_TransactionCurrency_id, CurrencyShareds.id
from CurrencyShareds 
INNER JOIN annexes
ON Amount_TransactionCurrency_id % 9223372036854775809 = CurrencyShareds.Id % 9223372036854775809

我怀疑这行得通,因为CE似乎使用了密度而不是直方图。其他类似的重写可能具有相同的效果。无法保证查询类型将来会继续正常运行。因此,您应该与Microsoft联系,以提高有一天解决该问题的可能性将其纳入发布的产品的可能性。


8

好吧,我希望我现在明白了-这就是我们的情况

给定

  1. 具有约100行的参考表(CurrencyShareds),但id很大,并且最小值,最大值之间的差异非常大-最小值:119,762,190,797,406,464与最大值:977,955,748,426,318,592
  2. 具有从FK到CurrencyShared的简单FK,但只使用了很少的货币的表(附件)-您可以看到IX_FK_Amount_TransactionCurrency的直方图列出了5个ID- 重要的那些“低” ID,因为没有使用其他ID。

当所有统计信息都是最新的时

CSelCalcExpressionComparedToExpression( QCOL: [test.MasterData].[dbo].[Annexes].Amount_TransactionCurrency_id x_cmpEq QCOL: [test.MasterData].[dbo].[CurrencyShareds].Id )

Loaded histogram for column QCOL: [test.MasterData].[dbo].[Annexes].Amount_TransactionCurrency_id from stats with id 7

Loaded histogram for column QCOL: [test.MasterData].[dbo].[CurrencyShareds].Id from stats with id 1

Selectivity: 0.01

那么为连接计算的选择性很好,因为100 * 107,131 * 0.01 = 107,131

如果货币共享的统计信息不是最新的,则

CSelCalcExpressionComparedToExpression( QCOL: [test.MasterData].[dbo].[Annexes].Amount_TransactionCurrency_id x_cmpEq QCOL: [test.MasterData].[dbo].[CurrencyShareds].Id )

Loaded histogram for column QCOL: [test.MasterData].[dbo].[Annexes].Amount_TransactionCurrency_id from stats with id 7

Loaded histogram for column QCOL: [test.MasterData].[dbo].[CurrencyShareds].Id from stats with id 1 *** WARNING: badly-formed histogram ***

Selectivity: 4.59503e-018

选择性急剧下降,因此联接的估计行数为1。

当直方图改变时

在我向附件添加一行以高ID刷新CurrencyShared之后,结果IX_FK_Amount_TransactionCurrency的直方图更改为

RANGE_HI_KEY         RANGE_ROWS    EQ_ROWS       DISTINCT_RANGE_ROWS  AVG_RANGE_ROWS
-------------------- ------------- ------------- -------------------- --------------
119762190797406475   0             173           0                    1
119762190797406478   0             868           0                    1
119762190797406481   0             107           0                    1
119762190797406494   0             105745        0                    1
119762190797406496   0             330           0                    1
119762190797406618   0             1             0                    1
119762190797406628   0             1             0                    1
977955748426318623   0             1             0                    1

有了这个直方图,问题就消失了,现在将新行添加到currencyshared不会导致基数估计值急剧下降。

这是为什么?

我怀疑这是sql2014 +中粗略直方图估计算法的工作方式,我将我的猜测基于这篇很棒的帖子https://www.sqlshack.com/join-estimation-internals/

粗直方图估计是一种新算法,即使在一般概念方面,其文献资料也很少。众所周知,与其一步一步地对齐直方图,不如将其与最小和最大直方图边界对齐。这种方法可能会引入较少的CE错误(但是并非总是如此,因为我们记得这只是一个模型)。

只是为了澄清一切-为什么我们在currencyshared中有如此奇怪的ID?

这非常简单-我们的ID在全球范围内是唯一的,并且部分基于时间戳(基于雪花的实现)。几年前在应用程序开始时就添加了最常见的货币,并且只有少数几种真正用于生产中,这就是为什么在直方图中只有ID为“低”的那些货币的原因。

问题出现在我们的测试环境中,其中一些自动化测试开始添加测试货币,从而导致某些查询执行时间更长或超时...

如何解决该问题?

我们将更频繁地更新那些参考表的统计信息(我们可能与其他类似的参考数据表有类似的问题)-这些表很小,因此更新统计信息不是问题

得到教训

  • 最新的统计数据很重要!!!
  • 普通的旧标识列不会导致这些问题:)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.