Tipps zur Diagnose einer manchmal langsamen Abfrage

20

Ich habe eine gespeicherte Prozedur, die Ergebnisse aus einer indizierten Ansicht über einen übergeordneten Index zurückgibt. Normalerweise läuft es schnell (~ 10ms), manchmal kann es bis zu 8 Sekunden dauern.

Hier ist ein Beispiel für eine zufällige Ausführung (Hinweis: Dies ist keine langsame Ausführung, aber der Abfragetext ist abgesehen vom übergebenen Wert derselbe):

declare @p2 dbo.IdentityType
insert into @p2 values(5710955)
insert into @p2 values(5710896)
insert into @p2 values(5710678)
insert into @p2 values(5710871)
insert into @p2 values(5711103)
insert into @p2 values(6215197)
insert into @p2 values(5710780)

exec ListingSearch_ByLocationAndStatus @statusType=1,@locationIds=@p2

Hier ist der SPROC:

ALTER PROCEDURE [dbo].[ListingSearch_ByLocationAndStatus]
    @LocationIds IdentityType READONLY,
    @StatusType TINYINT
AS
BEGIN
    SET NOCOUNT ON;

    SELECT      -- lots of fields
    FROM        [dbo].[ListingSearchView][a] WITH (NOEXPAND)
    INNER JOIN  @LocationIds [b] ON [a].[LocationId] = [b].[Id]
    WHERE       [a].[StatusType] = @statusType
    OPTION (RECOMPILE);

(Anmerkung: Ich habe den OPTION (RECOMPILE)Hinweis kürzlich nach einigem Rat hinzugefügt , aber es hat nicht geholfen.

Hier ist der Deckungsindex (Hinweis: Die Ansicht hat auch einen Clustered-Index ListingId, der eindeutig ist)

CREATE NONCLUSTERED INDEX [IX_ListingSearchView_ForAPI] ON [dbo].[ListingSearchView]
(
    [LocationId] ASC,
    [StatusType] ASC
)
INCLUDE ( -- all the fields in the query) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
GO

Ich habe einen Profiler-Trace mit Showplan-XML-Statistiken erstellt.

Hier ist eine langsame (6 Sekunden) und der entsprechende Plan: Bildbeschreibung hier eingeben

Sieht genau so aus, wie ich es erwartet habe, und ist der gleiche Plan, wenn die Abfrage schnell ist.

Hier ist die Vergrößerung des kostspieligen Teils des Plans, wenn das hilft: Bildbeschreibung hier eingeben

Hier ist das vollständige Schema der Anzeige- / Sicherungstabellen, falls dies hilfreich ist: https://pastebin.com/wh1sRcbQ

Anmerkungen:

  • Indizes wurden defragmentiert, Statistiken auf dem neuesten Stand.
  • Ursprünglich war die Abfrage inline gegen die Ansicht, aber ich bin zu SPROC gewechselt, um zu versuchen, mich zu stabilisieren. Hat nicht geholfen.
  • Hinzufügen eines WITH OPTION (RECOMPILE);Hinweises (hat nicht funktioniert, kann also kein Parameter-Sniffing durchgeführt werden?)
  • Andere Abfragen im System sind manchmal ebenfalls langsam und haben auch keine offensichtlichen Probleme in ihrem Plan.
  • Könnte sperren? Ich weiß nicht, wie ich es bestätigen soll.

Irgendwelche Ideen, was ich als nächstes versuchen könnte?

Vielen Dank

RPM1984
quelle
1
Kommentare sind nicht für eine längere Diskussion gedacht. Diese Unterhaltung wurde in den Chat verschoben . Jeder: Bitte nutzen Sie diese Möglichkeit zur weiteren Diskussion dieser Frage.
Paul White sagt GoFundMonica
angegebenen Link nicht working.proc Abfrage ist gerade nach vorne, gibt es riesige diff zwischen tatsächlichen und geschätzten Anzahl der Zeilen , die Fläche von concern.I ist denken Problem liegt in Sicht query.I denken unzureichend data.It sollte in der Nähe sein
KumarHarsh
Haben Sie versucht, WhoIsActive (von Adam Machanic) auszuführen, während die Abfrage ausgeführt wird? whoisactive.com Enthält Informationen zu wartenden Aufgaben, die Sie in die richtige Richtung weisen sollten.
MJH
Haben Sie etwas außerhalb der DB beseitigt, das dies verursacht? Vielleicht eine andere Anwendung, die eine synchrone E / A für den gemeinsam mit der Datenbank genutzten Speicher verursacht?
Johan

Antworten:

2

Ich denke wirklich nicht, dass die Verwendung von OPTION (RECOMPILE)eine effektive Möglichkeit ist, die Möglichkeit des Parameter-Sniffings auszuschließen.

Parameter-Sniffing tritt auf, wenn SQL mit einer bestimmten Abfrage verwirrt ist und diese als neu betrachtet, weil neue Parameter angezeigt werden. Dies ist langsam, da die Erstellung eines neuen Ausführungsplans zusätzliche Zeit in Anspruch nimmt.

Alles, was diese Option bewirkt, ist, SQL zu zwingen, jedes Mal einen neuen Plan zu erstellen, der so ziemlich dasselbe ist. Möglicherweise möchten Sie stattdessen Standardparameter mithilfe des folgenden Hinweises hinzufügen:

OPTION(OPTIMIZE FOR(@LocationIds='xx',@StatusType='xx'))

Stellen Sie bei der Auswahl der Standardparameter sicher, dass Sie einen statistisch repräsentativen Satz verwenden.
Dadurch wird jedes Mal derselbe Plan verwendet, und die Möglichkeit des Parameter-Sniffings wird ausgeschaltet. Sobald Sie dies getan haben und festgestellt haben, dass es nicht geholfen hat, ist es wahrscheinlich sicher, Parameter-Sniffing als Möglichkeit zu ignorieren.

Schütze McGavin
quelle
1

Versuchen Sie möglicherweise, die Reihenfolge zu erzwingen, sodass Sie wahrscheinlich immer mit der kleineren Tabelle (Variable) beginnen. Das wird allerdings schwierig mit Ansichten ...

    SELECT  -- lots of fields
    FROM    @LocationIds [b] WITH (NOEXPAND)
            INNER JOIN  [dbo].[ListingSearchView][a] WITH (NOEXPAND) 
                ON [a].[LocationId] = [b].[Id]
    WHERE   [a].[StatusType] = @statusType
    OPTION (FORCE ORDER);

Oder Sie können einen Loop-Join erzwingen, wenn Sie die Tabellenvariable im Allgemeinen so mit der Ansicht verbinden möchten, wodurch auch die Reihenfolge erzwungen wird.

    SELECT  -- lots of fields
    FROM    @LocationIds [b] WITH (NOEXPAND)
            INNER LOOP JOIN  [dbo].[ListingSearchView][a] WITH (NOEXPAND) 
                ON [a].[LocationId] = [b].[Id]
    WHERE   [a].[StatusType] = @statusType
    --leaving this here so you don't get an annoying warning 
    OPTION (FORCE ORDER);
Jeremy Giaco
quelle
0

Schreiben Sie den Namen der Store-Prozedur in den Query-Editor und wählen Sie die Store-Prozedur aus. Name & dann Wählen Sie den Plan für die geschätzte Ausführung anzeigen oder klicken Sie auf (Strg + L). unter dem Bild davon.

Bild des geschätzten Ausführungsplans anzeigen

Dann werden die Ausführungspläne direkt neben der Registerkarte Nachrichten im unteren Bereich des Abfrage-Editors angezeigt. dann in den grünen farbigen Linien die fehlenden Indexdetails anzeigen und mit der rechten Maustaste darauf klicken. Dann Neue Abfrage in neuem Tab öffnen und den INDEX erstellen. dann läuft deine Abfrage schnell.

Also habe ich diese Methode für die Diagnose der Abfrage verwendet, die langsam arbeiten. und es gibt auch so viele Abfragen oder Methoden, die Sie verwenden können.

Ausführungsplan mit Details

rks_dotnet
quelle
-1

Wenn Sie der Meinung sind, dass das Problem in der Blockierung liegt, empfehlen wir Ihnen, die optimistische Transaktionsisolationsstufe Read Committed Snapshot zu verwenden (bedenken Sie, dass dies den Aufwand für Ihre temporäre Datenbank erhöht).

VERWEIS: https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql/snapshot-isolation-in-sql-server

Wenn das Problem nicht in der Lese- / Schreibsperre liegt, können Sie versuchen, Ihrer Ansicht Indizes hinzuzufügen (die beste Auswahl an Indizes hängt von der Selektivität Ihrer Daten ab).

CREATE NONCLUSTERED INDEX IX_ListingSearchView (LocationID, StatusType) INCLUDE (other columns...)
Artashes Khachatryan
quelle
1
Der von Ihnen vorgeschlagene Index ist bereits vorhanden IX_ListingSearchView_ForAPI(siehe Skript in der Frage).
Paul White sagt GoFundMonica
1
Hey, danke für deine Antwort. Wie ich in meiner Frage gesagt habe, möchte ich wissen, was das Problem ist, bevor ich ein Update anwende. Ansonsten könnte ich nur das eigentliche Problem übersehen. Meine Frage ist, zuerst das Problem zu finden, dann die richtige Lösung.
RPM1984,
Können Sie diese langsame Abfrage in Ihrer lokalen Umgebung erhalten? Wenn dieselbe Abfrage manchmal langsam und manchmal schnell ausgeführt wird, hängt dies möglicherweise von den Eingabeparametern ab. Können Sie bitte die Anzahl der logischen Lesevorgänge und die Gesamtanzahl der von Ihrer langsamen Abfrage zurückgegebenen Zeilen angeben?
Artashes Khachatryan
@ArtashesKhachatryan ja, manchmal läuft es auch lokal langsam. Ich habe die Frage mit einem Ausführungsplan aktualisiert. Ich frage mich, ob es mit den langsamen Abfragen zusammenhängt, die mehr Zeilen als die schnellen zurückgeben, wie Sie gesagt haben.
RPM1984