SELECT TOP 1 nuit aux performances des requêtes; existe-t-il un moyen accessible à dba pour surmonter cela?


13

Dans une application de production (C # parlant à SQL Server 2014 Standard), il y a une requête qui ressemble à ceci, ci-dessous. La plupart du temps, il s'exécute en millisecondes. Mais parfois (pour certaines valeurs de @Id), cela devient fou et prend environ une minute. Ceci est plus long que le délai d'expiration de l'application, donc l'application échoue pour l'utilisateur.

Dans les cas "va fou", le jeu de résultats retourné est correctement vide, comme c'est le cas dans de nombreux cas, mais pas dans tous les autres.

Heureusement, cela est reproductible dans les environnements de production et de développement.

Le développeur dit que supprimer "TOP 1" de la requête, puis s'assurer que l'application consomme les lignes supplémentaires de l'ensemble de résultats, résout le problème de performances.

Le planificateur de requêtes ne suggère aucun index lorsqu'il TOP 1est présent. (en dev).

La modification de la requête et la correction de l'application sont en cours. Le déploiement prend un certain temps.

Ma question: existe-t-il un moyen accessible par DBA pour régler ou modifier l'instance SQL Server de production pour surmonter ce problème avant le changement d'application avec la nouvelle requête?

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;

L'avez-vous essayé comme sous-requête? Par exemple, sélectionnez le top 1 souscription_id de (sélectionnez [le reste de votre requête sans le top1]
SeanR

Peut-être qu'un réglage "normal" des requêtes fonctionnerait? Si les index sont suffisamment attractifs, les analyses disparaissent. C'est moins invasif qu'un guide de plan.
usr

Ainsi, les mêmes valeurs de font-elles @ID toujours «devenir fou»? Si c'est le cas, testez à l'aide de l'une de ces valeurs et capturez le plan de requête réel. Cela vous dira ce qui ne va pas. Si les «mauvaises» valeurs ne sont pas cohérentes, il semble probable que ce soit soit un reniflage de paramètre (voir la réponse de @ MartinSmith pour la solution), soit un problème de verrouillage impliquant la manière dont le client demande et consomme réellement l'ensemble de résultats.
RBarryYoung

Réponses:


12

Si vous ne pouvez pas modifier la requête, vous pouvez utiliser un guide de plan.

Testez les performances de la requête avec OPTION (QUERYTRACEON 4138)(aura besoin de quelqu'un avec des sysadminautorisations pour l'essayer).

Si cela produit une performance satisfaisante, vous pouvez l'appliquer avec un guide de plan. S'il ne produit pas de performances satisfaisantes, essayez de trouver un indice qui le fait. Peut OPTION (HASH JOIN, MERGE JOIN)- être si des boucles imbriquées inappropriées sont le problème. Vous devrez peut-être recourir à l' USE PLAN N'...'indice.

Une fois que vous connaissez les indices requis, vous pouvez les appliquer en utilisant les informations ici .


OPTION (QUERYTRACEON 4138)a fait l'affaire. Merci. Passons maintenant au tri des guides de plan.
O. Jones

0

pour les sourires, essayez ceci
`> est changé en> = donc pas exactement la même requête

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;

"La modification de la requête et la correction de l'application sont en cours. Le déploiement prend un certain temps." l'OP recherche une solution qui corrige les performances "en l'état".
Martin Smith

@MartinSmith Et quand ils déploient un correctif, cela peut être un meilleur correctif. Faire en sorte que l'application consomme les lignes supplémentaires entraînera d'autres modifications du programme.
paparazzo
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.