行の推定がひどく間違っている理由を理解するのに苦労しています。これが私のケースです。
単純な結合-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行を推定しますが、107131であり、ネストされたループ( link to plan )を実行することを選択します。 CurrencySharedsで統計が更新された後、見積もりは正常に行われ、マージ結合が選択されます( 新しいプランへのリンク )。 CurrencySharedsにレコードが1つだけ追加されるとすぐに、統計は「古く」なり、SQLは誤った推定に戻ります。
この単純なクエリについてはそれほど心配する必要はありませんが、これは大きなクエリの一部にすぎず、これがドミノの始まりです...
100レコードのテーブルに1行追加すると、なぜこのような損傷が発生するのですか?カーディナリティ推定トレースの出力を調べると、次の警告が表示されます***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 from stats with 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
2番目のインデックスの情報:
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
わかりました。理解できたと思います。
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
このヒストグラムでは問題が解消され、新しい行をCurrencySharesに追加しても、カーディナリティの推定が大幅に低下することはありません。
私はこれがsql2014 +での粗いヒストグラム推定アルゴリズムがどのように機能するかを疑っています、そして私はこの素晴らしい投稿に私の推測を基づいています https://www.sqlshack.com/join-estimation-internals/
Coarse Histogram Estimationは新しいアルゴリズムであり、一般的な概念の観点からも、ドキュメント化が少なくなっています。ヒストグラムを段階的に整列する代わりに、最小および最大のヒストグラム境界のみで整列することが知られています。この方法では、CEのミスが少なくなる可能性があります(ただし、これは単なるモデルであることを覚えているため、常にではありません)。
非常にシンプルです。IDはグローバルに一意であり、タイムスタンプに一部基づいています(実装は snowflake に基づいています)。最も一般的な通貨は数年前のアプリケーションの開始時に追加されたもので、実際に使用されているのは少数のみです。そのため、ヒストグラムには「低い」IDの通貨しかありません。
一部の自動化テストがテスト通貨を追加し始め、一部のクエリの実行が長くなったりタイムアウトしたりするテスト環境で問題が表面化しました...
これらの参照テーブルの統計を更新します(他の類似の参照データテーブルでも同様の問題が発生する可能性があります)-これらのテーブルは小さいため、統計の更新は問題ありません
あなたのヒストグラムに基づいて、私はできました repro 2017 CU6の問題。私はあなたが何か間違ったことをしているとは言いません。むしろ、カーディナリティの推定に問題があります。行を挿入する前に得られるものは次のとおりです。
行を挿入すると、最終的なカーディナリティの見積もりはかなり低下します。
ここにはかなり単純な再現があるので、 製品のフィードバックを送信 またはマイクロソフトでサポートチケットを開くことをお勧めします。サンプルデータを処理するいくつかの回避策を見つけることができましたが、そのうちの1つは受け入れられるかもしれません。
CurrencyShareds.Id
の一意のインデックスを削除します。一意のインデックスがないと、再現を機能させることができません。テーブルは小さいので、インデックスがなくても問題ないでしょう。もちろん、あなたがそれを維持する非常に良い理由があるかもしれません。。
select Amount_TransactionCurrency_id, CurrencyShareds.id
from CurrencyShareds
INNER JOIN annexes
ON Amount_TransactionCurrency_id % 9223372036854775809 = CurrencyShareds.Id % 9223372036854775809
CEがヒストグラムの代わりに密度を使用しているように見えるので、これはうまくいくと思います。他の同様の書き換えが同じ効果を持つ場合があります。クエリの種類が今後も引き続き機能するという保証はありません。そのため、Microsoftに連絡して、ある日、問題の修正がリリースされた製品に組み込まれる可能性を高める必要があります。