Как изменить фактический метод выполнения с «строки» на «пакетные» - Azure SQL Server - PullRequest
1 голос
/ 11 июня 2019

У меня есть некоторые серьезные проблемы.При вставке данных в мою базу данных я использую триггер INSTEAD OF INSERT, который выполняет запрос.

В моей базе данных TEST этот запрос занимает гораздо меньше 1 секунды для вставки одной строки.Однако в производственном процессе этот запрос выполняется НАМНОГО дольше (> 30 секунд на 1 строку).

При сравнении планов выполнения для них обоих, как представляется, существуют некоторые ОЧИСТНЫЕ различия:

  1. Тест содержит: «Фактический метод выполнения: пакет»
  2. Продукт имеет: «Фактический метод выполнения: строка»
  3. Тест содержит: «Фактическое количество строк: 1»
  4. Prod имеет: «Фактическое количество строк 92.000.000»

Менее недели назад производство работало аналогично тестированию.Но больше нет - к сожалению.

Может ли кто-нибудь из вас помочь мне выяснить, почему?

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

Prod  environment database - Using Row method and no predicate (really slow)

Test environment database - using Batch method and predicate (Fast)

Ответы [ 3 ]

1 голос
/ 12 июня 2019

Иногда использование подсказки запроса OPTION (hash Join) помогает принудительно использовать план запроса в режиме пакетной обработки.Следующий запрос, использующий образец базы данных AdventureWorks2012, демонстрирует то, что я говорю.

SELECT s.OrderDate, s.ShipDate, sum(d.OrderQty),avg(d.UnitPrice),avg(d.UnitPriceDiscount)
FROM Demo d 
join Sales.SalesOrderHeader s
on d.SalesOrderID=s.SalesOrderID
WHERE d.OrderQty>500
GROUP BY s.OrderDate,s.ShipDate

В приведенном выше запросе используется режим строки.С подсказкой запроса он затем использует пакетный режим.

SELECT s.OrderDate, s.ShipDate, sum(d.OrderQty),avg(d.UnitPrice),avg(d.UnitPriceDiscount)
FROM Demo d 
join Sales.SalesOrderHeader s
on d.SalesOrderID=s.SalesOrderID
WHERE d.OrderQty>500
GROUP BY s.OrderDate,s.ShipDate
OPTION(hash Join)
0 голосов
/ 12 июня 2019

Вы не можете форсировать обработку строк и пакетов непосредственно в SQL Server. Это решение на основе затрат в оптимизаторе. Вы можете (как вы заметили) форсировать сгенерированный план, который использует пакетный режим. Тем не менее, не существует конкретной модели «только использовать пакетный режим», поскольку она не всегда самая быстрая. Выполнение в пакетном режиме похоже на турбо на автомобильном двигателе - оно работает лучше всего, когда вы работаете с большими наборами рядов. Это может быть медленнее при небольших количествах OLTP-запросов.

Если у вас есть случай, когда у вас есть 1 строка против 92 М строк, то у вас есть большая проблема с проблемой, которая имеет высокую дисперсию в количестве строк, обработанных в запросе. Это может сделать очень трудным сделать запрос оптимальным для всех сценариев, если у вас есть чувствительность к параметрам или форма плана запроса внутри может создать случаи, когда иногда у вас есть только одна строка против 92M. В конечном счете, решения для такого рода проблем заключаются либо в использовании опции (перекомпиляции), если стоимость компиляции намного меньше, чем отклонение от наличия плохого плана, либо (как вы сделали) поиска конкретного плана в хранилище запросов, которое Вы можете заставить это работать достаточно хорошо для всех случаев.

Надеюсь, это поможет объяснить, что происходит под капотом.

0 голосов
/ 12 июня 2019

Я нашел несколько удовлетворительное решение моей проблемы.

Зайдя в хранилище запросов базы данных с помощью Microsoft SQL Server Management Studio, я смог принудительно назначить конкретный план для конкретного запроса - но только если план уже был составлен запросом.

...