Задача оценки мощности множества на внутреннем объединении

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
LeMaciek
источник

Ответы:

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

Я подозреваю, что это работает, потому что CE, кажется, использует плотность вместо гистограммы. Другие подобные переписывания могут иметь тот же эффект. Нет никаких гарантий, что этот тип запроса будет продолжать работать хорошо в будущем. Вот почему вам следует обратиться в Microsoft, чтобы повысить вероятность того, что однажды исправление вашей проблемы попадет в выпущенный продукт.

Джо Оббиш
источник
8

Хорошо, я надеюсь, что я понимаю это сейчас - так что это наш случай

Данный

  1. Справочная таблица (CurrencyShareds), содержащая ~ 100 строк, но идентификаторы большие, и минимальные, максимальные значения сильно различаются - мин: 119 762 190 797 406 464 против макс: 977 955 748 426 318 592
  2. Таблица (Приложения), которая имеет простой FK to 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 с высоким идентификатором, в результате гистограмма для 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

С этой гистограммой проблема исчезает, теперь добавление новой строки к currentcyshareds не вызывает резкого снижения оценки мощности.

Это почему?

Я подозреваю, что именно так работает алгоритм грубой оценки гистограммы в sql2014 +, и я основываю свои предположения на этом замечательном посте https://www.sqlshack.com/join-esvaluation-internals/

Грубая оценка гистограммы - это новый алгоритм, который менее документирован даже с точки зрения общих понятий. Известно, что вместо поэтапного выравнивания гистограмм он выравнивает их только по минимальным и максимальным границам гистограммы. Этот метод потенциально вносит меньше ошибок CE (но не всегда, потому что мы помним, что это всего лишь модель).

Просто чтобы прояснить все - почему у нас такие странные идентификаторы в currentcyshareds?

Это довольно просто - наши идентификаторы глобально уникальны и частично основаны на отметке времени (реализация основана на снежинке ). Наиболее распространенные валюты были добавлены в начале приложения несколько лет назад, и только те немногие действительно используются в производстве, поэтому в гистограмме есть только те, которые имеют «низкий» идентификатор.

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

Как решить проблему?

Мы будем обновлять статистику для этих справочных таблиц (у нас может быть похожая проблема с другими аналогичными таблицами справочных данных) чаще - эти таблицы маленькие, поэтому обновление статистики не является проблемой

Уроки выучены

  • Актуальная статистика важна !!!
  • простой старый столбец идентификации не вызовет этих проблем :)
LeMaciek
источник
Относительно грубого выравнивания: sqlperformance.com/2018/11/sql-optimizer/…
Пол Уайт 9