TSQL: Suchen Sie nach Abfragen, die zu viele SQL-Kompilierungen und SQL-Neukompilierungen verursachen

8

Ich möchte herausfinden, was die hohen SQL-Kompilierungen (keine Neukompilierungen) verursacht, die ich in Leistungsüberwachungszählern sehe.

Hier ist meine Meinung dazu: Wenn ich viele SQl-Kompilierungen sehe, bedeutet dies, dass die Abfragen auf unserem System aus folgenden Gründen nicht zwischengespeichert werden:

  • Viele Ad-hoc-Anfragen
  • Ausführen von Abfragen, die von SQl nicht zwischengespeichert werden, z.

    UPDATE table1 SET col1 = 'Zeichenfolge länger als 8000 Zeichen .....' WHERE key_column = some int

  • Pläne laufen ab und werden aus dem Cache entfernt, weil: Der Cache nicht genügend Speicherplatz hat oder Pläne nicht lange genug verwendet werden.

Das einzige, was der Erfassung von Cache-Einfügungen im Profiler nahe kommt, ist Gespeicherte Prozeduren-> SP: CacheInserts, aber es kümmert sich nur um den Cache für gespeicherte Prozeduren.

Also habe ich Folgendes versucht, um Ad-hoc-Anfragen zu erhalten:

SELECT [cp].[refcounts] -- when Refcounts becomes 0, plan is excluded from cache.
    , [cp].[usecounts] 
    , [cp].[objtype] 
    , st.[dbid] 
    , st.[objectid] 
    , st.[text] 
    , [qp].[query_plan] 
FROM sys.dm_exec_cached_plans cp     
CROSS APPLY sys.dm_exec_sql_text ( cp.plan_handle ) st     
CROSS APPLY sys.dm_exec_query_plan ( cp.plan_handle ) qp ;

Ich dachte, Abfragen, die die Kompilierungen verursacht haben, sollten solche mit objtype = Adhoc sein, aber dies könnte sich auch auf Neukompilierungen beziehen. Jetzt muss ich den Profiler ausführen, Abfragen erfassen, die zu Neukompilierungen führen, und ihn dann aus der obigen Liste entfernen.

Gehe ich in die richtige richtung

Gibt es eine einzige Abfrage, mit der ich nur SQL-Kompilierungen ohne zu viel Arbeit erstellen kann?

Ressourcen, die mir geholfen haben, das oben genannte Wissen zu erlangen:

http://social.msdn.microsoft.com/Forums/en/sqldatabaseengine/thread/954b4fba-3774-42e3-86e7-e5172abe0c83 http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=143946 http: //technet.microsoft.com/en-nz/library/cc966425(en-us).aspx
http://www.sqlservercentral.com/Forums/Topic914951-360-1.aspx

Jede Hilfe wird sehr geschätzt.

Manjot
quelle

Antworten:

7

Ich glaube nicht, dass Sie dies auf einfache Weise finden können, aber es ist trotzdem möglich, dies zu überwinden. Profiler bietet viele Ereignisklassentypen, mit denen die Leistung einer Abfrage analysiert werden kann. Starten Sie eine neue Profiler-Sitzung und überprüfen Sie folgende Ereignisse:

Performance: Performance statistics
Stored Procedures: RPC:Completed
TSQL: SQL:BatchCompleted
TSQL: SQL: BatchStarting

Aktivieren Sie das Kontrollkästchen Alle Spalten anzeigen und wählen Sie jede der Spalten unter Leistung: Nur Leistungsstatistikereignis aus. Der Rest der Ereignisse kann mit der Standardeinstellung belassen werden.

Wählen Sie als Nächstes Spaltenfilter aus und filtern Sie nach Datenbankname und / oder Anmeldename / Anwendungsname / Hostname usw., falls Sie diese kennen. Der Zweck besteht darin, die Anzahl der in Profiler bereitgestellten Zeilen zu begrenzen und sich nur auf Ihre Anforderungen zu konzentrieren.

Drücken Sie anschließend auf Ausführen und lassen Sie es eine Weile laufen (2-3 Minuten so lange wie nötig). Analysieren Sie die Ergebnisse unter Berücksichtigung von: Leistungsstatistikereignis.

Wenn Leistungsstatistiken häufig auftreten, bedeutet dies, dass der Plan einer Abfrage zum ersten Mal zwischengespeichert, kompiliert, neu kompiliert oder aus PlanCache entfernt wurde. Wenn eine Abfrage keinen Abfrageplan im Plan-Cache hat, werden meines Wissens zwei Zeilen des PerformanceStatistics- Ereignisses angezeigt , gefolgt von SQL: BatchStarting und SQL: BatchCompleted . Dies bedeutet, dass der Abfrageplan zuerst kompiliert, zwischengespeichert und dann die Abfrage gestartet und abgeschlossen wurde.

Sehen Sie sich die folgenden Spalten unter Leistungsstatistik an:

SPID - ID of the session on which the event occurred. You can use it to identify the       
       row on SQL:BatchCompleted event which will display the SQL Query text and other  
       usefull information (Read/Writes, StartTime/EndTime)
Duration - Total time, in microseconds, spent during compilation.
EventSubClass - 0 = New batch SQL text that is not currently present in the cache.
                1 = Queries within a stored procedure have been compiled.
                2 = Queries within an ad hoc SQL statement have been compiled.
                3 = A cached query has been destroyed and the historical performance         
                    data associated with the plan is about to be destroyed.
                4 = A cached stored procedure has been removed from the cache and the  
                    historical performance data associated with it is about to be 
                    destroyed.

                5 = A cached trigger has been removed from the cache and the historical  
                    performance data associated with it is about to be destroyed.

Unter Berücksichtigung der EventSubClass-Nummer können Sie herausfinden, was mit dem Abfrageplan passiert ist, und bestimmte Maßnahmen ergreifen. Darüber hinaus können Sie gespeicherten Prozeduren und TSQL- Ereignisklassen weitere Spalten hinzufügen, wenn Sie in HostName, WindowsUser oder anderen Informationen aus dem Profiler-Trace eingebettet sind. Der Trace kann auch in einer SQL-Tabelle gespeichert werden, wodurch die Analyse einfacher und viel anpassbarer wird. Hier ist ein Link, der mehr die Leistungsstatistik-Ereignisklasse beschreibt.

yrushka
quelle
4

Lassen Sie uns zuerst sehen, ob Druck auf den Cache ausgeübt wird.

select bpool_visible from sys.dm_os_sys_info
go

Multiplizieren Sie diese Zahl mit 8, um den Speicher in K zu erhalten. 75% davon von 0-4G + 10% davon von 4G-64G + 5% von mehr ist die Plan-Cache -Druckgrenze . Wenn Sie 75% dieses Grenzwerts erreichen, beginnt SQL Server mit dem Löschen von Plänen aus dem Cache. Diese Bereinigung erfolgt, wenn dem Cache ein neuer Abfrageplan hinzugefügt wird, sodass der Thread angehalten wird, um diese Arbeit auszuführen. Das zweite, was dazu führen kann, dass Pläne gelöscht werden, ist, wenn die Anzahl der Pläne das Vierfache der Anzahl der Hash-Buckets überschreitet (eine Hash-Tabelle ordnet einen plan_handle einem Plan zu). Auf einem 32-Bit-System gibt es 10.000 und auf einem 64-Bit-System 40.000.

select type, sum(pages_allocated_count) as pages_used from sys.dm_os_memory_objects 
where type in ('MEMOBJ_CACHESTOREOBJCP', 'MEMOBJ_CACHESTORESQLCP', 'MEMOBJ_CACHESTOREXPROC')
group by type
go

Die Entscheidung darüber, was gelöscht werden soll, wird nicht bei der Nutzung getroffen, sondern bei den Kosten des Plans. Die billigsten Pläne werden zuerst gelöscht (Kosten für Produktion, nicht Ausführung). Sie können dies sehen, wenn Sie die Spalten original_costund current_costzu Ihrer Abfrage hinzufügen sys.dm_exec_cached_plans. Ein Ad-hoc-Plan beginnt bei 0 und wird bei jeder Verwendung um 1 erhöht. Wenn Cache-Druck auftritt, subtrahiert SQL Server die Hälfte von den Kosten und löscht dann diejenigen, die 0 erreicht haben.

Wenn Sie viel Ad-hoc-SQL haben, versuchen Sie:

exec sp_reconfigure 'optimize for ad hoc workloads', 1
go
reconfigure
go

In diesem Modus speichert SQL Server nur einen "Stub" zwischen, der ungefähr 300 Byte groß ist (ein normaler Abfrageplan ist mindestens 24 KB groß) und einen Hash und einen Zeiger auf den SQL-Text enthält, wenn dann zum ersten Mal eine bestimmte SQL-Anweisung angezeigt wird Anschließend wird der vollständige Plan zwischengespeichert, wenn er erneut ausgeführt wird. Dies reduziert nicht unbedingt die Kompilierungen selbst, verringert jedoch den Speicherdruck im Plan-Cache.

Hinweis: Dies funktioniert im Jahr 2008, wurde 2005 nicht ausprobiert.

Ein weiterer Trick ist

alter database ... set parameterization forced
go

Dies führt dazu, dass SQL Server Konstanten als Parameter behandelt. Dies kann bei der Autoparameterisierungsfunktion hilfreich sein, mit der normalerweise Pläne für ähnliche SQL-Anweisungen zwischengespeichert werden. Bei Ad-hoc-SQL sollten die Abfragepläne zwischengespeichert werden, es sei denn, Ihr Server verfügt nur über sehr wenig Arbeitsspeicher. Dies hängt jedoch von genauen Textübereinstimmungen ab, sofern sie nicht parametrisiert werden können. In diesem Fall verhält es sich eher wie eine vorbereitete Abfrage.

Gaius
quelle
Vielen Dank! Ich wusste von dieser Option "Parametrisierung erzwungen", hatte aber Angst, sie zu verwenden. Der einzige Nachteil, den ich bei der Verwendung sehen kann, ist, dass es den Cache füllt. Habe ich recht?
Manjot
3

Haben Sie viele häufig ausgeführte SQL Server-Jobs in dieser Box? Beachten Sie, dass im Jahr 2005 die Agent-Jobabfragen NICHT zwischengespeichert werden und auch dazu führen können, dass der Cache aufgebläht und SQL kompiliert wird.

Sehen Sie sich die Anzahl der Pläne mit geringen Wiederverwendungszahlen an. Das sind deine Schuldigen.

Einige verwandte Hinweise zum Plan-Caching finden Sie weiter unten.

http://www.sqlskills.com/BLOGS/KIMBERLY/post/Plan-cache-adhoc-workloads-and-clearing-the-single-use-plan-cache-bloat.aspx

http://www.sqlskills.com/BLOGS/KIMBERLY/post/Clearing-the-cache-are-there-other-options.aspx

Sankar Reddy
quelle
0

Dieser Effekt wird als "Abfrageplanverschmutzung" bezeichnet, bei der viele ähnliche SQL-Abfragen separate, aber gleichwertige Ausführungspläne generieren.

Ad-hoc-Abfragen verursachen Overhead durch individuelles Parsen, fragen jedoch normalerweise keine Planverschmutzung ab, da ihre Pläne nicht gespeichert werden. Dies ist anders bei Abfragen mit nur einem Parameter (unter MS SQL Server). Diese werden wie eine parametrisierte Abfrage behandelt.

Es gibt einige typische Fälle für die Verschmutzung des Abfrageplans:

  • SQL-Abfragen mit nur einem fest codierten Literalparameter (wie 'ID auswählen, Name von Person mit ID = 1234')
  • insbesondere bei Verwendung mit Befehlen / gespeicherten Prozeduren, die die Datenbank zum Speichern des Abfrageplans zwingen, wie z. B. 'sp_prepexec' oder sp_executesql 'unter MSSQL (ich denke,' sofort ausführen 'unter Oracle funktioniert auf ähnliche Weise)
  • teilweise parametrisierte Abfragen mit großer Abweichung bei den 'hartcodierten' Literalwerten, z. B. 'select * from SoccerMatches sm where sm.Date>?' und sm.Date <? und HomeClubId = 5678 und GuestClubId = 1234 '. Diese speichern Abfragepläne aufgrund der Parameter, erstellen jedoch einen neuen Abfrageplan für jeden geänderten HomeClub oder GuestClub (insbesondere, da Datums- / Zeitwerte eine gute Gelegenheit sind, Parameter in viele DB-APIs einzuführen, wenn Abfragen aufgrund eines lokal unterschiedlichen Datums fehlschlagen Formate).
  • Eine weitere Quelle für die Verschmutzung von Abfrageplänen können Frameworks wie ADO.NET mit unzureichenden Treibern in Kombination mit Zeichenfolgen- / (n) -Varchar-Werten sein. Einige Implementierungen / Treiber setzen die Parametergrößen auf die tatsächliche Zeichenfolgenlänge, wodurch ein separater Abfrageplan für jede unterschiedliche Zeichenfolgenparameterlänge in der Abfrage erstellt wird. Best Practice scheint die Verwendung der maximalen Feldgröße (z. B. varchar (4000)) oder eines Treibers zu sein, der die richtige Länge angibt
Erik Hart
quelle