Другой план выполнения для одного и того же запроса - PullRequest
0 голосов
/ 06 марта 2019

У меня есть две идентичные базы данных SQL, которые содержат почти одинаковые записи в каждой из своих таблиц. Единственная разница между ними состоит в том, что один живет на моей локальной машине, а другой - в Azure. Тем не менее, после исследования проблемы с производительностью я обнаружил, что две базы данных создают разные планы выполнения для некоторых запросов. В качестве примера приведем простой запрос, выполнение которого занимает приблизительно 1 секунду.

select count(*) from Deposits
inner join households on households.id = deposits.HouseholdId
where CashierId = 'd89c8029-4808-4cea-b505-efd8279dc66d'

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

Local machine

Azure

Просто чтобы дать вам представление о том, что произошло, все работало идеально, пока я не сократил базу данных Azure до базовых 5 DTU. После этого некоторые запросы стали очень медленными, и я понятия не имел, почему. Я снова увеличил масштаб Db, но улучшений не увидел. Затем я перестроил индексы и заметил, что если я перестрою их в правильном порядке , запросы снова начнут работать, как и ожидалось. Тем не менее, я абсолютно не знаю, почему мне нужно перестроить их в каком-то определенном порядке и, еще меньше, как определить правильный порядок. Теперь у меня есть проблемы практически со всеми запросами, связанными с таблицей Deposits. Я попытался перестроить индексы, но не увидел никаких улучшений. Я подозреваю, что это связано с индексом PK, но я не совсем уверен. Таблица содержит приблизительно 300 тыс. Строк.

1 Ответ

1 голос
/ 06 марта 2019

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

SELECT SERVERPROPERTY(N'ProductVersion');

А как насчет оборудования, на котором они работают?ЦПУ?Объем памяти?Диски?Я имею в виду, что это Лазурь, верно?Трудно понять, какое именно серверное оборудование вы используете.Оптимизатор запросов SQL Server будет корректироваться с учетом аппаратных различий.Кроме того, даже если аппаратное и программное обеспечение было идентичным ... просто тот факт, что базы данных используются по-разному, может привести к различиям в статистике.При первом запуске запроса он оценивается и оптимизируется с использованием статистики.Все последующие вызовы этого запроса будут использовать этот изначально кэшированный план запроса.Столы меняются со временем, они становятся выше.Форма данных изменяется, а это означает, что старый план кэшированных запросов может в конечном итоге потерять популярность.Определенные вещи могут изменить данные и привести к изменению статистики, что, в свою очередь, приведет к аннулированию кэша плана запросов, например, к перестройке ваших индексов.Попробуй это.Чтобы принудительно задать новый план запросов для каждого оператора, добавьте оператор

OPTION (RECOMPILE)

в конец запросов.Это помогает или стабилизирует производительность?Кроме того - это растяжение - но могу ли я предположить, что вы не используете тот же самый запрос снова и снова?Имеет больше смысла, что вы не жестко запрограммировали этот GUID и что мы действительно создали план запроса для чего-то, что имеет @CashierID в качестве параметра?Если это так, то ваш существующий план запроса может быть жертвой перехвата параметров, когда план запроса, который вы извлекаете, был оптимизирован для какого-то определенного GUID и плохо работает при передаче чего-либо еще.

Для получения дополнительной информации о том, что делает это утверждение, посмотрите здесь .Чтобы лучше понять, почему сложно иметь идентичные базы данных, посмотрите здесь и здесь .

Удачи!Надеюсь, вы сможете разобраться.

...