Freunde von SQL Server und PerfMon finden

Auf dem Foto ist eine Szene aus der guten alten Komödie „Airplane“ zu sehen - die Boomer erinnern sich daran.



Sie ist nicht zufällig hier. Aber später nützlich.

Dba mag kein Perfmon


Das liegt überhaupt nicht daran, dass sich die PerfMon-Oberfläche mit Windows NT 3.1 (?) Nicht geändert hat und die Wärme von zweitausendstel zurückgibt. Übrigens kennt vielleicht jemand die Erklärung für diese seltsame Tatsache. Das Bedienfeld wird mehrmals im Jahr neu geschrieben. Sogar der Rechner wurde neu geschrieben. Aber nicht perfMon.

DBA denkt mit Schlagworten. Wenn ein guter DBA-Arzt an einem kranken SQL-Server ankommt, öffnet er seinen Koffer, und im Koffer gibt es eine große Anzahl von Vierteln, die ihm treu dienen. Er nimmt den kürzesten von ihnen aus dem Gedächtnis. Manchmal kann ein DBA die Metriken von PerfMon untersuchen - physische Festplatte oder Länge der Festplattenwarteschlange. Ein echter DBA erhält jedoch seine eigenen SQL Server-Metriken, nicht über PerfMon, sondern mit einem Patch wie dem folgenden:

select * from sys.dm_os_performance_counters 
  where object_name='SQLServer:Buffer Manager' 
    and counter_name like 'Page life expectancy%' 
	and instance_name=''

Wenn IT-Vertreter, die von der DBA-Sphäre getrennt sind, ihn fragen: "Welche Metriken sollen wir sammeln?" (Nun, es gibt alle Arten von Splunk, Squared-Up usw.), dann beginnt der DBA, über Skripte nachzudenken, und der Rest über Perfmon-Metriken. Gleichzeitig versuchen sie in der Regel, alle Metriken auf dem DBA abzulegen. In diesem Fall ist das Bild in seiner Überlastung nutzlos. Und dann hilft mir ein kurzer Videoclip aus dem Film "Airplane" .

Infolgedessen schreibt DBA Keri, die alle N Minuten Statistiken auf eine Platte in der DBAtasks-Datenbank schreiben. Erkennst du dich selbst?

Advocate Devil (Perfmon)


Trotzdem sind Perfmon-Zähler ein Standardwerkzeug. Sie können protokolliert und Warnungen festgelegt werden. Vor allem aber gibt es eine große Anzahl von Systemen, die diese Metriken von vielen Computern in einem zentralen Repository "zusammenführen", damit Sie sie analysieren und schöne (und nicht wie Perfmon) Diagramme erstellen können.

Es stellt sich heraus, dass wir uns mit der SQL-Welt und der PerfMon-Welt anfreunden können!

Unten werde ich zeigen wie.

Jetzt werden die Einzelheiten gehen


Als Beispiel zeigen wir, wie Metriken exportiert werden, die SQL selbst nicht in PerfMon veröffentlicht. Zum Beispiel die folgende Abfrage:

select
  convert(numeric(10,2),round(((sum(version_store_reserved_page_count)*1.0)/128.00),2)),
  convert(numeric(10,2),round(((sum(user_object_reserved_page_count)*1.0)/128.00),2)),
  convert(numeric(10,2),round(((sum(internal_object_reserved_page_count)*1.0)/128.00),2))
from
  tempdb.sys.dm_db_file_space_usage;

Gibt die Menge an Tempdb-Speicherplatz zurück, die vom Versionsspeicher (für Snapshot), Benutzerobjekten (Registerkarte #tab und ##) und Sortier- / temporären Speicherplatz verwendet wird. Lassen Sie uns Metriken für sie erstellen (18+, Teams sind nicht dokumentiert)

dbcc addinstance ('SQLServer:User Settable', 'TempDB version store KB')
dbcc addinstance ('SQLServer:User Settable', 'TempDB user store KB')
dbcc addinstance ('SQLServer:User Settable', 'TempDB sort store KB')

Dadurch werden drei Metriken in SQLServer -> UserSettable -> Query erstellt. Die Metriken sind Ganzzahlen - int (nicht bigint). Außerdem wird ihre Bedeutung so interpretiert, wie sie ist. Das heißt, wenn Sie ein Delta vom vorherigen Wert benötigen, ist dies Ihr Anliegen. In diesem Fall müssen wir den Metriken jedoch nur Werte zuweisen:

declare @TEMPDBver int, @TEMPDBuser int, @TEMPDBsort int
select

@TEMPDBver = convert(numeric(10,2),round(((sum(version_store_reserved_page_count) *1.0)/128.00),2)),
@TEMPDBuser = convert(numeric(10,2),round(((sum(user_object_reserved_page_count) *1.0)/128.00),2)),
@TEMPDBsort = convert(numeric(10,2),round(((sum(internal_object_reserved_page_count) *1.0)/128.00),2))
from tempdb.sys.dm_db_file_space_usage;

if @TEMPDBver is not null    
  dbcc setinstance ('SQLServer:User Settable', 'Query', 
    'TempDB version store KB', @TEMPDBver)
if @TEMPDBuser is not null   
  dbcc setinstance ('SQLServer:User Settable', 'Query', 
   'TempDB user store KB', @TEMPDBuser)
if @TEMPDBsort is not null   
  dbcc setinstance ('SQLServer:User Settable', 'Query', 
    'TempDB sort store KB', @TEMPDBsort)

Eigentlich ist das alles. Rufen Sie diesen Code jetzt regelmäßig auf und alles wird funktionieren.

Delta-Zähler


Lassen Sie uns nun einen Delta-Zähler erstellen. Dies ist das Sperrzeitlimit in ms.

dbcc addinstance ('SQLServer:User Settable', 'LOCK ms per s')

Hier können Sie mir widersprechen, dass eine solche Metrik bereits existiert:

select * from sys.dm_os_performance_counters 
  where counter_name like 'Lock Wait Time (ms)%' 
    and instance_name='_Total'
    and object_name='SQLServer:Locks'

Diese Metrik ist jedoch erst irgendwann konsistent. Wie Sie sich erinnern, ist jede Datenbank im Universum konsistent, wenn Protonen instabil sind. Das heißt, wenn Sie eine Sperre erstellen und den Wert dieser Metrik betrachten, wächst sie nicht! Und erst am Ende der Sperre springt der Wert für die gesamte Wartezeit stark an. In der Grafik erhalten Sie anstelle des erwarteten "Plateaus" einen scharfen Peak, der auch Ihre Skalierung entlang der Y-Achse

beeinträchtigt . Das gleiche Problem besteht bei kvery:

select sum(wait_time_ms) 
  from sys.dm_os_wait_stats 
  where wait_type like 'LCK_%'

Daher müssen wir die Zeit der aktuellen zur Zeit der 'abgeschlossenen' Sperren addieren:

declare @NEWlock bigint
select @NEWlock=sum(wait_time_ms) 
  from sys.dm_os_wait_stats 
  where wait_type like 'LCK_%' -- finished waits
select @NEWlock=@NEWlock+isnull(sum(waittime),0) 
  from master.dbo.sysprocesses 
  where blocked>0 and lastwaittype like 'LCK_%' -- waits in progress

Diese Abfrage gibt bereits das richtige Plateau auf der Karte an.

Jetzt müssen wir das Delta vom vorherigen Wert betrachten. Es gibt zwei Möglichkeiten:

  • Entwerfen Sie einen Prozess als Job, der häufig aufgerufen wird (z. B. einmal pro Minute). Erstellen Sie eine Beschriftung, um vorherige Werte zu speichern. Tatsächlich ist es oft schlecht, einen Job aufzurufen (Overhead + Wettbewerb um die Ausführungshistorie von Jobs), und Sie können auf eine zusätzliche Platte verzichten:
  • Erstellen Sie mit waitfor einen Prozess, der in einer Endlosschleife ausgeführt wird. Der Prozess merkt sich den vorherigen Wert in der Variablen. Wir werden den Prozess als Job mit zwei Zeitplänen verarbeiten: beim Start und einmal pro Stunde (falls der Job fällt, wird er neu gestartet)

Im zweiten Fall ist es durchaus möglich, alle fünf Sekunden oder noch öfter einen Zyklus durchzuführen. Also bekommen wir:

declare @OLDlock bigint, @NEWlock bigint
declare @lock int, @seconds int = 5 -- must match WAITFOR
loop:
  set @OLDlock=@NEWlock -- shift new to old
  select @NEWlock=sum(wait_time_ms) 
    from sys.dm_os_wait_stats 
	where wait_type like 'LCK_%' -- finished waits
  select @NEWlock=@NEWlock+isnull(sum(waittime),0) 
    from master.dbo.sysprocesses 
	where blocked>0 and lastwaittype like 'LCK_%' -- waits in progress
  set @lock=(@NEWlock-@OLDlock)/@seconds -- this is delta
  if @lock is not null    
    dbcc setinstance ('SQLServer:User Settable', 'Query', 
	  'LOCK ms per s', @lock)
  waitfor delay '00:00:05' 
goto loop

Bitte beachten Sie, dass beim ersten Ausführen einer DBCC-Schleife diese übersprungen wird (was korrekt ist), da @OLDlock (und sperren) wird null sein.

All Articles