Проблема оцінки кардинальності при внутрішньому з'єднанні


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 і вибирає вкладений цикл ( посилання на план ). Після оновлення статистики на 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 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. Я не можу змусити дозволу працювати без унікального індексу. Таблиця невелика, тому, можливо, можна обійтись без індексу. Звичайно, у вас можуть бути дуже вагомі причини збереження.
  2. Матеріалізуйте результати приєднання до темп-таблиці. Виходячи з вашого питання, важливо отримати розумну оцінку на цьому кроці, щоб більший запит працював добре. Темп-таблиця - це один із способів зробити це.
  3. Використовуйте спадщину CE. Я не можу змусити проблему відтворити її. Звичайно, це може мати негативні наслідки для решти запиту.
  4. Випробуйте оптимізатор запитів за допомогою дурного коду. Наприклад, у моєму тестуванні чудово працює наступне перезапис:

.

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

Я підозрюю, що це працює, тому що СЕ використовує щільність замість гістограми. Інші подібні переписування можуть мати той же ефект. Немає гарантій, що в майбутньому тип запиту буде працювати добре. Ось чому вам слід зв’язатися з корпорацією Майкрософт, щоб покращити шанси, що одного разу виправлення вашої проблеми перетворить її на випущений продукт.


8

Гаразд, я сподіваюся, що я це зараз розумію - так це наш випадок

Дано

  1. Довідкова таблиця (CurrencyShareds) з ​​~ 100 рядками, але ідентифікатори великі, і min, максимальні значення сильно відрізняються - хв: 119,762,190,797,406,464 проти max: 977,955,748,426,318,592
  2. Таблиця (Додатки) , який має простий FK для CurrencyShared, але лише деякі валюти використовуються - ви можете бачити , що гістограма для списків IX_FK_Amount_TransactionCurrency 5 іди - і , що важливо тільки ці «низький» Ідентифікатори, як і інші не використовуються.

Коли всі статистичні дані актуальні, тоді

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.

Коли гістограма змінюється

Після того, як я додаю один рядок до додатків, які посилаються на CurrencyShared з високим id, то в результаті гістограма для 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/

Оцінка грубої гістограми - це новий алгоритм і менш задокументований, навіть з точки зору загальних понять. Відомо, що замість вирівнювання гістограм поетапно вони вирівнюють їх лише з мінімальними та максимальними межами гістограми. Цей метод потенційно вводить менше помилок CE (проте не завжди, тому що ми пам'ятаємо, що це лише модель).

Просто для того, щоб все було зрозуміло - чому ми маємо такі дивні ідентифікатори в currencyshareds?

Це досить просто - наші ідентифікатори є унікальними у всьому світі та частково базуються на позначках часу (реалізація на основі сніжинки ). Найпоширеніші валюти були додані на початку програми кілька років тому, і лише ті декілька реально використовуються у виробництві, тому в гістограмі є лише ті, у кого "низький" ідентифікатор.

Проблема виникла в наших тестових середовищах, де деякі автоматизовані тести почали додавати тестові валюти, внаслідок чого деякі запити виконувались довше або таймаут ...

Як виправити проблему?

Ми оновлюватимемо статистику для цих довідкових таблиць (у нас може бути схожа проблема з іншими подібними таблицями довідкових даних) частіше - ці таблиці невеликі, тому оновлення статистики не є проблемою

Вивчені уроки

  • Актуальна статистика важлива !!!
  • звичайний старий стовпець ідентичності не викликав би цих проблем :)

Щодо грубого вирівнювання: sqlperformance.com/2018/11/sql-optimizer/…
Пол Білий 9
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.