SELECT TOP 1 prejudica o desempenho da consulta; existe uma maneira acessível por dba para superar isso?

13

Em um aplicativo de produção (C # conversando com o SQL Server 2014 Standard), há uma consulta parecida com esta, abaixo. Na maioria das vezes, ele é executado em milissegundos. Mas, ocasionalmente (para certos valores de @Id), fica louco e leva um minuto ou mais. Como o tempo limite do aplicativo é maior, o aplicativo falha para o usuário.

Nos casos "enlouquece", o conjunto de resultados retornado está corretamente vazio, como em muitos casos, mas não em todos os outros.

Felizmente, isso é reproduzível nos ambientes de produção e desenvolvimento.

O desenvolvedor diz que remover "TOP 1" da consulta e garantir que o aplicativo consuma as linhas extras do conjunto de resultados resolvem o problema de desempenho.

O planejador de consultas não sugere índices quando TOP 1está presente. (em dev).

A alteração da consulta e a correção do aplicativo estão em andamento. A implementação demora um pouco.

Minha pergunta: Existe alguma maneira acessível por DBA de ajustar ou ajustar a instância do SQL Server de produção para solucionar esse problema antes que o aplicativo seja alterado com a nova consulta?

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;
O. Jones
fonte
Você já tentou isso como uma subconsulta? Por exemplo, selecione o top 1 subscription_id a partir de (selecione [o restante da sua consulta sem o top1])
SeanR 07/07
Talvez algum ajuste de consulta "normal" funcione? Se os índices forem atraentes o suficiente, as varreduras desaparecem. Isso é menos invasivo do que um guia de plano.
usr
Então, os mesmos valores de @ID sempre o fazem "enlouquecer"? Nesse caso, teste usando um desses valores e capture o plano de consulta real. Isso lhe dirá o que está errado. Se os valores "ruins" não forem consistentes, é provável que isso ocorra com a detecção de parâmetros (consulte a resposta da @ MartinSmith para solução) ou com um problema de bloqueio envolvendo como o cliente realmente solicita e consome o conjunto de resultados.
precisa saber é o seguinte

Respostas:

12

Se você não pode alterar a consulta, pode usar um guia de plano.

Teste o desempenho da consulta com OPTION (QUERYTRACEON 4138) (será necessário alguém com sysadminpermissões para tentar isso).

Se isso produzir um desempenho satisfatório, você poderá aplicá-lo com um guia de plano. Se não produzir um desempenho satisfatório, tente encontrar uma dica. Possivelmente OPTION (HASH JOIN, MERGE JOIN)se loops aninhados inapropriados forem o problema. Pode ser necessário recorrer à USE PLAN N'...'dica.

Depois de conhecer as dicas necessárias, você pode aplicá-las usando as informações aqui .

Martin Smith
fonte
OPTION (QUERYTRACEON 4138)fez o truque. Obrigado. Agora, vamos resolver os guias de plano.
O. Jones
0

para sorrisos, tente isso
>> é alterado para> = para não ser exatamente a mesma consulta

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;
paparazzo
fonte
"A alteração da consulta e a correção do aplicativo estão em andamento. A distribuição demora um pouco." o OP está procurando uma solução que corrige o desempenho "como está".
Martin Smith
@MartinSmith E quando eles lançam uma correção, essa pode ser uma solução melhor. Fazendo o aplicativo consumir as linhas extras, haverá outras alterações no programa.
Paparazzo