|
Неоптимальный выбор плана запроса
|
|||
---|---|---|---|
#18+
Добрый день. MS SQL Windows Server 2016 Standard 15.0.2080.9. База данных используется для 1С. Есть простенький запрос, который выполняется очень часто (текст пойман на стороне SQL сервера в том виде, в котором его сгенерировала 1С). Код: sql 1.
Иногда приходит немного другой текст запроса, в котором вместо 0x0000045C другая подобная константа. Для таблицы _AccumRg49944 задан кластерный индекс Код: sql 1. 2. 3. 4. 5. 6. 7. 8.
Также имеется уникальный индекс Код: sql 1. 2. 3. 4. 5. 6. 7.
Этот индекс является покрывающим для запроса. В чем собственно проблема. Приведенный запрос обычно выполняется быстро (несколько мс). При этом используется второй индекс. В плане запроса 2 операции: Код: plaintext 1.
План запроса при этом выглядит по другому, используется кластерный индекс Код: plaintext 1.
Почему так происходит - мне непонятно. Пока что я придумал только один способ решения данной проблемы. Это перестроить второй индекс. Код: sql 1.
После выполнения данной операции снова начинает использоваться "быстрый" план. Но мне кажется, что это метод "из пушки по воробьям". Я хочу разобраться, что же происходит и почему вдруг оптимизатор решает выбрать другой план. Дополнительная информация. Автообновление статистики включено. Поле _Fld2467 во всей таблице имеет одно значение. Для поля _RecorderTRef плотность статистики 0.08333334 Для поля _RecorderRRef плотность статистики 0.0002060581 Размер таблицы около 85 млн строк, 95Гб. Размер второго индекса - 3.5Гб В течении дня записи в таблицу добавляются и удаляются. Я оцениваю, что осуществляется примерно 10-12 тысяч операций в сутки. Прошу подсказать, в какую сторону смотреть, чтобы разобраться, почему вдруг меняется план выполнения. Почему сервер решает не использовать заведомо покрывающий индекс. Какие еще операции обслуживания можно выполнять, чтобы помочь выбирать верный индекс? ... |
|||
:
Нравится:
Не нравится:
|
|||
15.09.2021, 10:57 |
|
Неоптимальный выбор плана запроса
|
|||
---|---|---|---|
#18+
agorbunov, Дело в том, что в первом плане у вас перед выводом стоит SORT - довольно-таки дорогая операция. А стоит он там потому, что вывод отсортирован по _Period, а в "покрывающем" индексе между ключом индекса и _Period (доставшемся из ключа кластерного индекса) стоит ещё _LineNo. То есть, формально вывод индекса _AccumRg49944_2 не отсортирован по _Period и СУБД выполняет эту операцию самостоятельно. В какой-то момент статистики портятся, сиквел решает "хватит это терпеть" и выбирает индекс, вывод которого уже будет отсортирован по _Period. И, конечно, ошибается, потому что из-за устаревших статистик не видит, что первый вариант был лучше. В общем, надо либо убрать _LineNo из "покрывающего" индекса (но тогда он может стать неуникальным). Либо добавить новый индекс: Код: sql 1. 2. 3. 4. 5. 6.
P.S. планы лучше и смотреть, и прикладывать в XML. Там много всего интересного по сравнению со старым текстовым форматом. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.09.2021, 11:16 |
|
Неоптимальный выбор плана запроса
|
|||
---|---|---|---|
#18+
agorbunov, по каким то причинам удаляется план выполнения (перестроение индексов, статисика..). затем первым выполняется запрос с значением параметра, под который оптимизатор считает выгодным использовать кластерный индекс. этот план запроса сохраняется и далее используется. когда перестраиваете индекс, то удаляется план выполнения запроса. и если первым пройдет запрос с более частым параметром, то фиксируется план. и все становится хорошо. пока случайным образом не совпадет неудачный вариант. интересный вопрос, можно ли с этим что то сделать...наверное единственный вариант - изменить запрос в конфигурации, который идет с вторым параметром. чтобы его текст немного отличался. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.09.2021, 11:20 |
|
Неоптимальный выбор плана запроса
|
|||
---|---|---|---|
#18+
0wl, Спасибо за подробный ответ. Действительно, в "быстром" плане операция SORT оценена в 4 раза дороже, чем Index Seek. К сожалению, я несколько ограничен в настройке индексов из-за платформы 1С. Попробую чаще обновлять статистику по этой таблице или индексу, понаблюдаю за поведением. spenov, Запрос, который я выложил, сгенерирован платформой. В 1С он выглядит еще проще и параметр там только один. Насколько я понимаю, второй параметр платформой 1С специально поставляется напрямую в текст запроса константой. Как раз чтобы исключить parameter sniffing. В реальности, должно приходить порядка 15 разных запросов, отличающихся только вторым параметром. Меняя тип параметра в 1С я должен получать другой запрос - с другим условием на _RecorderTRef. По идее, для каждого из них должен храниться свой план. Спасибо за идею, попробую отследить, какие именно запросы начинают "тормозить". Отличается ли второй параметр в этих запросах, или из всей пачки "долгий" план выбирается только для одного единственного значения второго параметра. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.09.2021, 12:42 |
|
Неоптимальный выбор плана запроса
|
|||
---|---|---|---|
#18+
Мои наблюдения кончились следующим. Как описано тут Положительный побочный эффект от перестроения индекса , при перестроении индекса обновляется статистика по нему с полным сканированием всех строк. Поэтому в проблемный момент вместо перестроения индекса я обновил статистику Код: sql 1.
Это привело к ожидаемому эффекту - планы запроса снова стали использовать этот индекс. Перед этим я пробовал пересчитать статистику с параметрами по умолчанию, без указания WITH FULLSCAN. Это эффекта не дало. Теперь я столкнулся с другой ситуацией. При пересчете статистики сиквел использует последние параметры. Автоматически обновленная статистика также была собрана по всем строкам таблицы. И в итоге, изначальной проблемы с выбором неверного индекса я теперь не наблюдаю. Где можно почитать про стратегии выбора параметра SAMPLE и расчет количества строк для обновления статистики? Статья UPDATE STATISTICS мне не сильно в этом помогла. Мне кажется, что пересчитывать статистику по всем строкам может быть не лучшим решением. И еще хочу разобраться, почему пересчет статистики с параметрами по умолчанию не дает желаемого эффекта. ... |
|||
:
Нравится:
Не нравится:
|
|||
23.09.2021, 09:20 |
|
Неоптимальный выбор плана запроса
|
|||
---|---|---|---|
#18+
agorbunov И еще хочу разобраться, почему пересчет статистики с параметрами по умолчанию не дает желаемого эффекта. Потому, что "часть таблицы" <> "целая таблица". Сервер тупо и незатейливо использует "скока-то там процентов" строк "сверху в порядке кластерного индекса". Если эти "строки сверху" заполнены чем-то не тем - статистика ошибается. У тя в выборочную статистику попадают строки одного _Period. В данном случае, надо НЕ обновлять, а ОТКЛЮЧИТЬ обновление статистики. И будет тебе щастье... И серверу полегчает. ... |
|||
:
Нравится:
Не нравится:
|
|||
23.09.2021, 09:37 |
|
|
start [/forum/topic.php?fid=46&fpage=14&tid=1684274]: |
0ms |
get settings: |
8ms |
get forum list: |
12ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
203ms |
get topic data: |
12ms |
get forum data: |
2ms |
get page messages: |
47ms |
get tp. blocked users: |
1ms |
others: | 261ms |
total: | 554ms |
0 / 0 |