powered by simpleCommunicator - 2.0.50     © 2025 Programmizd 02
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Неоптимальный выбор плана запроса
6 сообщений из 6, страница 1 из 1
Неоптимальный выбор плана запроса
    #40097741
agorbunov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день.

MS SQL Windows Server 2016 Standard 15.0.2080.9.
База данных используется для 1С.

Есть простенький запрос, который выполняется очень часто (текст пойман на стороне SQL сервера в том виде, в котором его сгенерировала 1С).
Код: sql
1.
SELECT TOP 1 T1._Period FROM dbo._AccumRg49944 T1 WHERE ((T1._Fld2467 = @P1)) AND ((T1._RecorderTRef = 0x0000045C AND T1._RecorderRRef = @P2)) ORDER BY (T1._Period)

Иногда приходит немного другой текст запроса, в котором вместо 0x0000045C другая подобная константа.

Для таблицы _AccumRg49944 задан кластерный индекс
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
CREATE UNIQUE CLUSTERED INDEX [_AccumRg49944_1] ON [dbo].[_AccumRg49944]
(
	[_Fld2467] ASC,
	[_Period] ASC,
	[_RecorderTRef] ASC,
	[_RecorderRRef] ASC,
	[_LineNo] ASC
)


Также имеется уникальный индекс
Код: sql
1.
2.
3.
4.
5.
6.
7.
CREATE UNIQUE NONCLUSTERED INDEX [_AccumRg49944_2] ON [dbo].[_AccumRg49944]
(
	[_Fld2467] ASC,
	[_RecorderTRef] ASC,
	[_RecorderRRef] ASC,
	[_LineNo] ASC
)

Этот индекс является покрывающим для запроса.

В чем собственно проблема.
Приведенный запрос обычно выполняется быстро (несколько мс). При этом используется второй индекс.
В плане запроса 2 операции:
Код: plaintext
1.
Index Seek (_AccumRg49944_2 SEEK: _Fld2467, _RecorderTRef, _RecorderRRef)
SORT (TOP 1)
Однако, спустя примерно сутки, этот запрос начинает выполнять по 30-40 секунд.
План запроса при этом выглядит по другому, используется кластерный индекс
Код: plaintext
1.
Index Seek (_AccumRg49944_1 SEEK: _Fld2467  WHERE: _RecorderTRef, _RecorderRRef)
TOP 1

Почему так происходит - мне непонятно.
Пока что я придумал только один способ решения данной проблемы. Это перестроить второй индекс.
Код: sql
1.
ALTER INDEX [_AccumRg49944_2] ON [dbo].[_AccumRg49944] REBUILD PARTITION = ALL

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

Дополнительная информация.
Автообновление статистики включено.
Поле _Fld2467 во всей таблице имеет одно значение.
Для поля _RecorderTRef плотность статистики 0.08333334
Для поля _RecorderRRef плотность статистики 0.0002060581

Размер таблицы около 85 млн строк, 95Гб.
Размер второго индекса - 3.5Гб

В течении дня записи в таблицу добавляются и удаляются. Я оцениваю, что осуществляется примерно 10-12 тысяч операций в сутки.

Прошу подсказать, в какую сторону смотреть, чтобы разобраться, почему вдруг меняется план выполнения. Почему сервер решает не использовать заведомо покрывающий индекс.
Какие еще операции обслуживания можно выполнять, чтобы помочь выбирать верный индекс?
...
Рейтинг: 0 / 0
Неоптимальный выбор плана запроса
    #40097748
0wl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
0wl
Гость
agorbunov,

Дело в том, что в первом плане у вас перед выводом стоит SORT - довольно-таки дорогая операция. А стоит он там потому, что вывод отсортирован по _Period, а в "покрывающем" индексе между ключом индекса и _Period (доставшемся из ключа кластерного индекса) стоит ещё _LineNo. То есть, формально вывод индекса _AccumRg49944_2 не отсортирован по _Period и СУБД выполняет эту операцию самостоятельно.

В какой-то момент статистики портятся, сиквел решает "хватит это терпеть" и выбирает индекс, вывод которого уже будет отсортирован по _Period. И, конечно, ошибается, потому что из-за устаревших статистик не видит, что первый вариант был лучше.

В общем, надо либо убрать _LineNo из "покрывающего" индекса (но тогда он может стать неуникальным). Либо добавить новый индекс:
Код: sql
1.
2.
3.
4.
5.
6.
Create unique index new_index on [dbo].[_AccumRg49944] 
([_Fld2467] ASC, 
[_RecorderTRef] ASC,
[_RecorderRRef] ASC, 
[_Period], 
[_LineNo] ASC)



P.S. планы лучше и смотреть, и прикладывать в XML. Там много всего интересного по сравнению со старым текстовым форматом.
...
Рейтинг: 0 / 0
Неоптимальный выбор плана запроса
    #40097749
spenov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
agorbunov,

по каким то причинам удаляется план выполнения (перестроение индексов, статисика..). затем первым выполняется запрос с значением параметра, под который оптимизатор считает выгодным использовать кластерный индекс. этот план запроса сохраняется и далее используется.

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

интересный вопрос, можно ли с этим что то сделать...наверное единственный вариант - изменить запрос в конфигурации, который идет с вторым параметром. чтобы его текст немного отличался.
...
Рейтинг: 0 / 0
Неоптимальный выбор плана запроса
    #40097771
agorbunov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
0wl,
Спасибо за подробный ответ.
Действительно, в "быстром" плане операция SORT оценена в 4 раза дороже, чем Index Seek.
К сожалению, я несколько ограничен в настройке индексов из-за платформы 1С.
Попробую чаще обновлять статистику по этой таблице или индексу, понаблюдаю за поведением.

spenov,
Запрос, который я выложил, сгенерирован платформой. В 1С он выглядит еще проще и параметр там только один.
Насколько я понимаю, второй параметр платформой 1С специально поставляется напрямую в текст запроса константой. Как раз чтобы исключить parameter sniffing.
В реальности, должно приходить порядка 15 разных запросов, отличающихся только вторым параметром. Меняя тип параметра в 1С я должен получать другой запрос - с другим условием на _RecorderTRef. По идее, для каждого из них должен храниться свой план.
Спасибо за идею, попробую отследить, какие именно запросы начинают "тормозить". Отличается ли второй параметр в этих запросах, или из всей пачки "долгий" план выбирается только для одного единственного значения второго параметра.
...
Рейтинг: 0 / 0
Неоптимальный выбор плана запроса
    #40099462
agorbunov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Мои наблюдения кончились следующим.

Как описано тут Положительный побочный эффект от перестроения индекса , при перестроении индекса обновляется статистика по нему с полным сканированием всех строк.

Поэтому в проблемный момент вместо перестроения индекса я обновил статистику
Код: sql
1.
UPDATE STATISTICS [_AccumRg49944] ([_AccumRg49944_2]) WITH FULLSCAN


Это привело к ожидаемому эффекту - планы запроса снова стали использовать этот индекс.

Перед этим я пробовал пересчитать статистику с параметрами по умолчанию, без указания WITH FULLSCAN.
Это эффекта не дало.

Теперь я столкнулся с другой ситуацией. При пересчете статистики сиквел использует последние параметры. Автоматически обновленная статистика также была собрана по всем строкам таблицы. И в итоге, изначальной проблемы с выбором неверного индекса я теперь не наблюдаю.

Где можно почитать про стратегии выбора параметра SAMPLE и расчет количества строк для обновления статистики? Статья UPDATE STATISTICS мне не сильно в этом помогла.
Мне кажется, что пересчитывать статистику по всем строкам может быть не лучшим решением.
И еще хочу разобраться, почему пересчет статистики с параметрами по умолчанию не дает желаемого эффекта.
...
Рейтинг: 0 / 0
Неоптимальный выбор плана запроса
    #40099467
aleks222
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
agorbunov

И еще хочу разобраться, почему пересчет статистики с параметрами по умолчанию не дает желаемого эффекта.


Потому, что "часть таблицы" <> "целая таблица".
Сервер тупо и незатейливо использует "скока-то там процентов" строк "сверху в порядке кластерного индекса".
Если эти "строки сверху" заполнены чем-то не тем - статистика ошибается.
У тя в выборочную статистику попадают строки одного _Period.

В данном случае, надо НЕ обновлять, а ОТКЛЮЧИТЬ обновление статистики.
И будет тебе щастье...
И серверу полегчает.
...
Рейтинг: 0 / 0
6 сообщений из 6, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Неоптимальный выбор плана запроса
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]