내부 조인의 카디널리티 추정 문제


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 행을 추정하지만 107131이며 중첩 루프를 수행하도록 선택합니다 ( plan에 링크 ). CurrencyShareds에 대한 통계가 업데이트 된 후에는 추정이 양호하고 병합 조인이 선택됩니다 ( 새 계획에 대한 링크 ). CurrencyShareds에 하나의 레코드 만 추가되면 통계는 "stale"이되고 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 in stats from 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

답변:


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 vs 최대 : 977,955,748,426,318,592
  2. CurrencyShared에 간단한 FK가 있지만 통화가 거의 사용되지 않는 테이블 (부속서)-IX_FK_Amount_TransactionCurrency에 대한 히스토그램에 5 개의 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

이 히스토그램을 사용하면 문제가 사라지고 통화 공유에 새 행을 추가해도 카디널리티 추정이 급격히 떨어지지 않습니다.

왜 그런 겁니까?

나는 이것이 굵은 막대 그래프 추정 알고리즘이 sql2014 +에서 작동하는 방식이라고 생각하며,이 위대한 게시물 https://www.sqlshack.com/join-estimation-internals/

Coarse Histogram Estimation은 일반적인 개념의 관점에서도 새로운 알고리즘이며 문서화가 적습니다. 히스토그램을 단계별로 정렬하는 대신 최소 및 최대 히스토그램 경계로만 정렬하는 것으로 알려져 있습니다. 이 방법은 잠재적으로 적은 CE 실수를 유발합니다 (그러나 이것이 단지 모델이라는 것을 기억하기 때문에 항상 그런 것은 아닙니다).

모든 것을 분명히하기 위해-왜 우리는 통화 공유에 이상한 ID가 있습니까?

우리의 ID는 전 세계적으로 독특하며 타임 스탬프 ( 눈송이를 기반으로 한 구현)를 기반으로 합니다. 가장 일반적인 통화는 몇 년 전에 응용 프로그램이 시작될 때 추가되었으며 실제로는 그 중 몇 개만이 실제로 생산에 사용되므로 히스토그램에는 "낮은"ID를 가진 통화 만 있습니다.

이 문제는 테스트 환경에서 나타 났으며 일부 자동화 테스트는 테스트 통화를 추가하기 시작하여 일부 쿼리가 더 오래 실행되거나 시간 초과됩니다.

문제를 해결하는 방법?

이러한 참조 테이블에 대한 통계를 업데이트합니다 (다른 유사한 참조 데이터 테이블과 유사한 문제가있을 수 있음).이 테이블은 작으므로 통계 업데이트는 문제가되지 않습니다.

교훈

  • 최신 통계가 중요합니다 !!!
  • 일반 오래된 ID 열은 이러한 문제를 일으키지 않습니다. :)

대략적인 정렬에 관하여 : sqlperformance.com/2018/11/sql-optimizer/…
Paul White 9
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.