SELECT TOP 1 вредит производительности запросов; Есть ли доступный способ преодолеть это?

13

В производственном приложении (C # общается с SQL Server 2014 Standard) ниже приведен запрос, который выглядит следующим образом. Большую часть времени это выполняется в миллисекундах. Но иногда (для определенных значений @Id) это сходит с ума и занимает минуту или около того. Это больше, чем время ожидания приложения, поэтому приложение перестает работать для пользователя.

В случаях «сходит с ума» возвращенный набор результатов является правильно пустым, как и во многих, но не во всех других случаях.

К счастью, это воспроизводимо как в производственной среде, так и в среде разработки.

Разработчик говорит, что удаление «TOP 1» из запроса, а затем проверка того, что приложение использует дополнительные строки набора результатов, устраняет проблему производительности.

Планировщик запросов не предлагает никаких индексов, когда TOP 1присутствует. (в dev).

Идет изменение запроса и исправление приложения. Развертывание занимает некоторое время.

Мой вопрос: есть ли какой-нибудь доступный для DBA способ настройки или настройки производственного экземпляра SQL Server, чтобы преодолеть эту проблему до того, как приложение изменится с новым запросом?

SELECT TOP 1
       subscription_id 
  FROM subscription AS sub
  JOIN billing_info AS bi ON bi.billing_info_id = sub.billing_info_id   
  JOIN person_group AS apg ON apg.person_id = bi.person_id
  JOIN pplan ON pplan.plan_id = sub.plan_id
  JOIN product ON product.product_id = [plan].product_id 
  JOIN product_attribute ON product_attribute.product_id = product.product_id 
 WHERE apg.group_id = @Id
   AND apg.start_date < GETDATE()
   AND (apg.end_date IS NULL OR apg.end_date > GETDATE()) 
   AND (sub.end_date IS NULL OR sub.end_date > GETDATE()) 
   AND product_attribute.attribute_type = 'special feature' 
   AND product_attribute.attribute_data = '1' 
 ORDER BY sub.start_date ASC;
О. Джонс
источник
Вы пробовали это как подзапрос? Например, выберите top 1 subscription_id из (выберите [остаток вашего запроса без top1]
SeanR
Может быть, какая-то "нормальная" настройка запросов будет работать? Если индексы достаточно привлекательны, сканы исчезают. Это менее агрессивно, чем руководство плана.
USR
Значит, одни и те же значения @ID всегда заставляют его «сходить с ума»? Если это так, то протестируйте, используя одно из этих значений, и запишите фактический план запроса. Это скажет вам, что происходит не так. Если «плохие» значения не согласованы, то вполне вероятно, что это либо сниффинг параметров (см. Ответ @ MartinSmith для решения), либо проблема блокировки, связанная с тем, как клиент на самом деле запрашивает и использует набор результатов.
RBarryYoung

Ответы:

12

Если вы не можете изменить запрос, вы можете использовать руководство плана.

Проверьте производительность запроса с помощью OPTION (QUERYTRACEON 4138)(для этого потребуется кто-то с sysadminразрешениями).

Если это дает удовлетворительные результаты, вы можете применить это к плану руководства. Если это не дает удовлетворительной производительности, попробуйте найти подсказку, которая это делает. возможноOPTION (HASH JOIN, MERGE JOIN) проблема заключается в неправильных вложенных циклах. Возможно, вам придется прибегнуть к USE PLAN N'...'подсказке.

Как только вы знаете требуемые подсказки, вы можете применить их, используя приведенную здесь информацию .

Мартин Смит
источник
OPTION (QUERYTRACEON 4138)сделал свое дело. Благодарю. Теперь переходим к плану руководства.
О. Джонс
0

для ухмылок дайте этому попытку
`> изменено на> =, поэтому не точно такой же запрос

SELECT TOP 1
       subscription_id 
  FROM subscription AS sub
  JOIN billing_info AS bi 
        ON bi.billing_info_id = sub.billing_info_id   
  JOIN person_group AS apg 
        ON apg.person_id = bi.person_id 
       AND apg.group_id = @Id
       AND apg.start_date < GETDATE()
       AND isnnull(apg.end_date, GETDATE()) >= GETDATE()             
  JOIN pplan 
        ON pplan.plan_id = sub.plan_id
       AND isnnull(sub.end_date, GETDATE()) >= GETDATE()
  JOIN product 
        ON product.product_id = [plan].product_id 
  JOIN product_attribute 
        ON product_attribute.product_id = product.product_id 
       AND product_attribute.attribute_type = 'special feature' 
       AND product_attribute.attribute_data = '1' 
 ORDER BY sub.start_date ASC;
папараццо
источник
«Идет изменение запроса и исправление приложения. Развертывание занимает некоторое время». ОП ищет решение, которое фиксирует производительность «как есть».
Мартин Смит
@MartinSmith И когда они выдают исправление, это может быть лучше. Заставить приложение использовать дополнительные строки будут другие изменения программы.
Папараццо