SELECT TOP 1 beeinträchtigt die Abfrageleistung. gibt es eine dba-zugängliche möglichkeit, dies zu überwinden?

13

In einer Produktionsanwendung (C # im Gespräch mit SQL Server 2014 Standard) wird im Folgenden eine Abfrage angezeigt, die folgendermaßen aussieht. Die meiste Zeit läuft es in Millisekunden. Aber gelegentlich (für bestimmte Werte von @Id) geht es verrückt und dauert eine Minute oder so. Dies ist länger als das App-Timeout, sodass die App für den Benutzer fehlschlägt.

In den "Goes Nuts" -Fällen ist die zurückgegebene Ergebnismenge korrekt leer, wie in vielen, aber nicht allen anderen Fällen.

Zum Glück ist dies sowohl in der Produktions- als auch in der Entwicklungsumgebung reproduzierbar.

Der Entwickler sagt, "TOP 1" aus der Abfrage zu entfernen und dann sicherzustellen, dass die App die zusätzlichen Zeilen der Ergebnismenge verbraucht, behebt das Leistungsproblem.

Der Abfrageplaner schlägt keine Indizes vor, wenn TOP 1vorhanden. (in dev).

Die Abfrage wird geändert und die App repariert. Der Rollout dauert eine Weile.

Meine Frage: Gibt es eine DBA-zugängliche Möglichkeit, die SQL Server-Produktionsinstanz zu optimieren oder zu optimieren, um dieses Problem zu beheben, bevor die App mit der neuen Abfrage geändert wird?

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
quelle
Haben Sie es als Unterabfrage versucht? Wählen Sie z. B. Top 1-Abonnement-ID aus (wählen Sie [den Rest Ihrer Abfrage ohne Top 1] aus)
SeanR
Vielleicht würde eine "normale" Abfrageoptimierung funktionieren? Wenn die Indizes attraktiv genug sind, verschwinden die Scans. Das ist weniger invasiv als ein Planführer.
USR
Also machen die gleichen Werte @ID immer "verrückt"? Wenn ja, testen Sie einen dieser Werte und erfassen Sie den tatsächlichen Abfrageplan. Das wird dir sagen, was falsch läuft. Wenn die "schlechten" Werte nicht konsistent sind, ist dies wahrscheinlich entweder ein Parameter-Sniffing (siehe @ MartinSmiths Antwort zur Lösung) oder ein Sperrproblem, bei dem es darum geht, wie der Client die Ergebnismenge tatsächlich anfordert und verarbeitet.
RBarryYoung

Antworten:

12

Wenn Sie die Abfrage nicht ändern können, können Sie einen Planungsleitfaden verwenden.

Testen Sie die Leistung der Abfrage mit OPTION (QUERYTRACEON 4138)(hierfür ist eine Person mit sysadminBerechtigungen erforderlich ).

Wenn dies zu einer zufriedenstellenden Leistung führt, können Sie dies mit einem Planungsleitfaden anwenden. Wenn die Leistung nicht zufriedenstellend ist, suchen Sie einen entsprechenden Hinweis. Möglicherweise OPTION (HASH JOIN, MERGE JOIN)liegt das Problem bei ungeeigneten verschachtelten Schleifen. Möglicherweise müssen Sie auf den USE PLAN N'...'Hinweis zurückgreifen .

Sobald Sie die erforderlichen Hinweise kennen, können Sie sie mithilfe der Informationen hier anwenden .

Martin Smith
quelle
OPTION (QUERYTRACEON 4138)hat den Trick gemacht. Vielen Dank. Nun zum Aussortieren von Planführern.
O. Jones
0

für grins probier das mal aus
`> wird geändert in> = also nicht exakt die selbe abfrage

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
quelle
"Das Ändern der Abfrage und das Reparieren der App wird durchgeführt. Der Rollout dauert eine Weile." Das OP sucht nach einer Lösung, die die Leistung "wie sie ist" behebt.
Martin Smith
@MartinSmith Und wenn sie einen Fix rollen, kann dies ein besserer Fix sein. Wenn Sie die App dazu bringen, die zusätzlichen Zeilen zu belegen, werden andere Programmänderungen vorgenommen.
Paparazzo