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:
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:
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
Antworten:
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:
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.
quelle
Versuchen Sie möglicherweise, die Reihenfolge zu erzwingen, sodass Sie wahrscheinlich immer mit der kleineren Tabelle (Variable) beginnen. Das wird allerdings schwierig mit Ansichten ...
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.
quelle
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.
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.
quelle
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).
quelle
IX_ListingSearchView_ForAPI
(siehe Skript in der Frage).