OPTION FORCE ORDER повышает производительность, пока строки не будут удалены

9

У меня есть несколько сложный запрос SQL Server 2008 (около 200 строк довольно плотного SQL), который не выполнялся так, как мне было нужно. Со временем производительность упала с примерно 0,5 секунды до примерно 2 секунд.

Взглянув на план выполнения, стало совершенно очевидно, что путем изменения порядка соединений производительность может быть улучшена. Я сделал, и это сделало ... примерно до 0,3 секунды. Теперь запрос имеет подсказку «OPTION FORCE ORDER» , и жизнь хороша.

Вместе со мной сегодня, очистка базы данных. Я архивирую около 20% строк, не предпринимая никаких действий в соответствующей базе данных, за исключением удаления строк ... план выполнения ПОЛНОСТЬЮ скрыт . Он полностью неверно оценивает, сколько строк вернут определенные поддеревья, и (например) заменяет:

<Hash>

с

<NestedLoops Optimized='false' WithUnorderedPrefetch='true'>

Теперь время запроса увеличивается примерно с 0,3 до 18 с. (!) Просто потому, что я удалил строки. Если я уберу подсказку запроса, я вернусь к времени запроса около 2 с. Лучше, но хуже.

Я воспроизвел проблему после восстановления базы данных в нескольких местах и ​​на серверах. Простое удаление около 20% строк из каждой таблицы всегда вызывает эту проблему.

  1. Является ли это нормальным для порядка принудительного соединения, чтобы сделать оценки запроса полностью неточными (и, следовательно, время запроса непредсказуемым)?
  2. Должен ли я ожидать, что мне придется либо принять неоптимальную производительность запросов, либо наблюдать за ней как ястреб и часто вручную редактировать подсказки запросов? Или, может быть, намекает на каждое присоединение? .3 к 2 с большой удар, чтобы взять.
  3. Очевидно ли, почему оптимизатор взорвался после удаления строк? Например, «да, потребовалось сканирование образца, и поскольку я ранее заархивировал большинство строк в истории данных, образец дал редкие результаты, поэтому он недооценил необходимость операции сортированного хэша»?

Если вы хотите увидеть планы выполнения, пожалуйста, предложите место, где я могу их опубликовать. В противном случае, я выбрал самый потрясающий бит. Вот фундаментальная неправильная оценка, числа в скобках (предполагаемые: фактические) строки.

                             /  Clustered Index Scan (908:7229)
Nested Loops (Inner Join) --<
                             \  NonClustered Index Seek (1:7229)

Обратите внимание, что внутренний цикл должен сканировать 908 строк, но вместо этого сканирует 52 258 441. Если бы это было точно, эта ветвь работала бы около 2 мс, а не 12 с. Перед удалением строк эта оценка внутреннего соединения была отключена всего в 2 раза и выполнялась как совпадение хэша для двух кластеризованных индексов.

Shannon
источник

Ответы:

6

Является ли это нормальным для порядка принудительного соединения, чтобы сделать оценки запроса полностью неточными (и, следовательно, время запроса непредсказуемым)?

Использование FORCE ORDER не делает оценки неточными, удаление строк сделало. Принудительное обновление статистики в таблице может улучшить точность оценки.

Должен ли я ожидать, что мне придется либо принять неоптимальную производительность запросов, либо наблюдать за ней как ястреб и часто вручную редактировать подсказки запросов? Или, может быть, намекает на каждое присоединение? .3 к 2 с большой удар, чтобы взять.

Желательно, чтобы оптимизатор получил информацию, необходимую для создания наилучшего плана, без использования подсказки FORCE ORDER. Таким образом, он должен лучше справляться с изменениями в основном распределении данных, не требуя ручного вмешательства. Тем не менее, если характер данных таков, что количество элементов может значительно различаться от часа к часу или от дня к часу, рассмотрите возможность использования руководства плана, чтобы убедиться, что план фиксирован.

Очевидно ли, почему оптимизатор взорвался после удаления строк? Например, «да, потребовалось сканирование образца, и поскольку я ранее заархивировал большинство строк в истории данных, образец дал редкие результаты, поэтому он недооценил необходимость операции сортированного хэша»?

Вы не упомянули количество строк в проблемных таблицах, но вполне вероятно, что удаления тоже:

  • не удалось удалить достаточно строк, чтобы вызвать обновление статистики. Это должно происходить, когда было изменено 20% строк, но есть возможность использовать флаг трассировки 2371 для включения динамического порога.
  • инициировал обновление статистики, но собранный образец не был репрезентативным. Исправьте это, запустив ручное обновление WITH FULLSCAN .

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

Марк Стори-Смит
источник
Просто пояснение, это, вероятно, семантика: «Использование FORCE ORDER не делает оценки неточными, как удаление строк». Таким образом, вы думаете, что это просто случайный шанс, что удаление "FORCE ORDER" настолько улучшило запрос? Намек не привел оптимизатор к тому, чтобы полагаться на статистику, на которую он бы предпочел уделять меньше внимания, или не был обнаружен в тесте приложения, потому что эта менее надежная статистика редко была ключевой?
Шеннон
Я думаю, что да, в том смысле, что предпочтительный выбор плана оптимизаторами справляется с неточной статистикой, а план, возникший из-за принудительного порядка соединения, - нет. Я не знаю, как FORCE ORDER вызывает какие-либо изменения в оценке статистики, кто-то другой вмешается, если узнает что-то противоположное. Также необходимо учитывать, подходит ли значение, выбранное вами для ОПТИМИЗАЦИИ. Может быть, статистика в порядке, но вы вынуждаете план на основе значения, которое не является репрезентативным.
Марк Стори-Смит
Правильно. У меня та же проблема производительности, когда параметры передаются точно так же, как я их оптимизировал. Еще раз спасибо.
Шеннон