Ist es möglich, LRU-K-Werte in SQL Server anzuzeigen?

21

In SQL Server sys.dm_os_memory_cache_entriesist es möglich , sowohl die ursprünglich Kosten für einen Eintrag im Cache sowie die aktuell Kosten für den Cache - Eintrag (zu betrachten original_costund current_costjeweils). Die DMV sys.dm_os_buffer_descriptorsenthält eine Aufzeichnung der aktuell im Speicher befindlichen Seiten sowie einige Metadaten zu den Seiten. Ein interessanter Informationsblock, der im DVM nicht verfügbar ist, sind die LRU-K-Werte für die Datenseiten.

Ist es möglich, die LRU-K-Werte für Datenseiten im Pufferpool in SQL Server abzurufen? Wenn das so ist, wie?

Jeremiah Peschka
quelle
Ist das versionsspezifisch?
JNK
1
@JNK - In einer perfekten Welt, nein, aber solange es auf SQL Server 2012 funktioniert, mache ich mir keine Sorgen.
Jeremiah Peschka

Antworten:

21

Es gibt in der Tat keine sinnvolle Möglichkeit, dies zu tun, soweit ich sehen kann.

Die andere Antwort erwähnt DBCC PAGEund überlässt es dem Leser, die Details herauszufinden. Vom Experimentieren gehe ich davon aus, dass sie bedeuten bUse1.

Dies berücksichtigt nicht, dass DBCC PAGEes sich um eine Nutzung der Seite handelt und der Wert aktualisiert wird, bevor er uns angezeigt wird.

Ein Skript, das dies demonstriert, ist unten abgebildet (die Ausführung dauert 12 Sekunden).

USE tempdb;

CREATE TABLE T(X INT);

INSERT INTO T VALUES(1);

DECLARE @DBCCPAGE NVARCHAR(100);

SELECT @DBCCPAGE = 'DBCC PAGE(0,' + CAST(file_id AS VARCHAR) + ',' + CAST(page_id AS VARCHAR) + ',0) WITH TABLERESULTS;'
FROM   T CROSS APPLY  sys.fn_PhysLocCracker (%%physloc%%)

DECLARE @DbccResults TABLE 
(
      ID INT IDENTITY,
      ParentObject VARCHAR(1000)NULL,
      Object VARCHAR(4000)NULL,
      Field VARCHAR(1000)NULL,
      ObjectValue VARCHAR(MAX)NULL
)    
INSERT INTO @DbccResults EXEC(@DBCCPAGE)  
WAITFOR DELAY '00:00:07'
INSERT INTO @DbccResults EXEC(@DBCCPAGE)  
WAITFOR DELAY '00:00:05'
INSERT INTO @DbccResults EXEC(@DBCCPAGE)             

SELECT *
FROM @DbccResults   
WHERE Field = 'bUse1'    
ORDER BY ID

EXEC(@DBCCPAGE) 

DROP TABLE T

Typische Ergebnisse sind

+----+--------------+-------------------------+-------+-------------+
| ID | ParentObject |         Object          | Field | ObjectValue |
+----+--------------+-------------------------+-------+-------------+
|  8 | BUFFER:      | BUF @0x00000002FE1F1440 | bUse1 |       54938 |
| 49 | BUFFER:      | BUF @0x00000002FE1F1440 | bUse1 |       54945 |
| 90 | BUFFER:      | BUF @0x00000002FE1F1440 | bUse1 |       54950 |
+----+--------------+-------------------------+-------+-------------+

Mit dem zweiten Ergebnis ist

+---------+-------------------------+--------------+--------------------+
| BUFFER: | BUF @0x00000002FE1F1440 | bpage        | 0x00000002F4968000 |
| BUFFER: | BUF @0x00000002FE1F1440 | bhash        | 0x0000000000000000 |
| BUFFER: | BUF @0x00000002FE1F1440 | bpageno      | (1:120)            |
| BUFFER: | BUF @0x00000002FE1F1440 | bdbid        | 8                  |
| BUFFER: | BUF @0x00000002FE1F1440 | breferences  | 0                  |
| BUFFER: | BUF @0x00000002FE1F1440 | bcputicks    | 0                  |
| BUFFER: | BUF @0x00000002FE1F1440 | bsampleCount | 0                  |
| BUFFER: | BUF @0x00000002FE1F1440 | bUse1        | 54950              |
| BUFFER: | BUF @0x00000002FE1F1440 | bstat        | 0x9                |
| BUFFER: | BUF @0x00000002FE1F1440 | blog         | 0x1c9a             |
| BUFFER: | BUF @0x00000002FE1F1440 | bnext        | 0x0000000000000000 |
+---------+-------------------------+--------------+--------------------+

Die Ausgabe nach der Verzögerung von 7 Sekunden wird um 7 und nach der Verzögerung von 5 Sekunden um 5 erhöht.

Es scheint also klar zu sein, dass diese LRU-Werte seit einiger Zeit Sekunden sind. Durch einen Neustart des SQL Server-Dienstes wird die Epoche nicht geändert, durch einen Neustart des Computers jedoch.

Der Wert überschreitet sich alle 65.536 Sekunden, daher gehe ich davon aus, dass nur so etwas verwendet wird system_up_time mod 65536

Dies lässt eine unbeantwortete Frage in meinem Kopf (irgendwelche Abnehmer?). SQL Server verwendet LRU-Kmit K=2laut internals Buch. Sollte es nicht eine geben bUse2? Wenn ja, wo ist das?

Es gibt eine Möglichkeit, den bUse1Wert zu beobachten , ohne ihn zu ändern, von der ich jedoch weiß, und die wird hier von Bob Ward demonstriert .

Hängen Sie einen Debugger an den SQL Server-Prozess an und zeigen Sie den referenzierten Speicher für die Speicheradresse der Pufferstruktur an (siehe Abbildung 0x00000002FE1F1440oben).

Ich habe das gleich nach dem Ausführen des obigen Skripts gemacht und Folgendes gesehen.

Bildbeschreibung hier eingeben

(Aus früheren Experimenten habe ich herausgefunden, dass die hervorgehobenen Bytes die einzigen waren, die sich zwischen den Läufen geändert haben, sodass dies definitiv die richtigen sind.)

Ein überraschender Aspekt ist, dass SELECT CAST(0xc896 as int)= 51350.

Das sind genau 3600 (eine Stunde) weniger als von gemeldet DBCC PAGE.

Ich glaube, dass dies ein Versuch ist, Seiten, die im Cache gehalten werden, durch einen Aufruf von sich DBCC PAGEselbst zu missbilligen . Für eine "normale" Seite wird diese einstündige Anpassung nicht durchgeführt. Nach dem Rennen

SELECT *
FROM T

SELECT ((ms_ticks) % 65536000) / 1000 AS [Roughly Expected Value]
FROM sys.dm_os_sys_info

Der im Speicher angezeigte Wert ist wie erwartet.

Der DBCCBefehl aktualisiert diesen Wert tatsächlich zweimal. Einmal um

sqlmin.dll!BPool::Touch()  + 0x3bfe bytes   
sqlmin.dll!BPool::Get()  + 0x12e bytes  
sqlmin.dll!LatchedBuf::ReadLatch()  + 0x14f bytes   
sqlmin.dll!UtilDbccDumpPage()  + 0x364 bytes    
sqlmin.dll!DbccPage()  + 0xfa bytes 
sqllang.dll!DbccCommand::Execute()  + 0x153 bytes

Mit dem höheren Wert dann nochmal um

sqlmin.dll!LatchedBuf::FreeAndUnlatch()  + 0x71 bytes   
sqlmin.dll!UtilDbccDumpPage()  + 0x545 bytes    
sqlmin.dll!DbccPage()  + 0xfa bytes 
sqllang.dll!DbccCommand::Execute()  + 0x153 bytes   

Mit dem unteren.

Ich kenne keine Möglichkeit, Pufferadressen für Seiten abzurufen, ohne DBCC BUFFER/ in DBCC PAGEirgendeiner Weise zu verwenden, und unter Verwendung dieser beiden Änderungen den Wert, den wir untersuchen möchten!

Martin Smith
quelle
3
Nun, dies ist eine Möglichkeit, Weihnachten zu verbringen. :-)
RBarryYoung
3
@RBarryYoung Beats spielen Trivial Pursuit!
Martin Smith
Wenn ich Bonuspunkte für die ordnungsgemäße Verwendung eines Debuggers geben könnte, würde ich.
Jeremiah Peschka
1
Gut gemacht! (Und großartige Debugging-Fähigkeiten!)
DBArgenis
@DBArgenis - Danke! Schade, dass es keine praktikable Lösung zu geben scheint. Es könnte sehr informativ sein, wenn wir dies leicht sehen könnten.
Martin Smith
8

Wie ich Herrn Peschka auf Twitter bereits sagte, werden diese Informationen in der BUF-Struktur gespeichert, in der die Seite gespeichert ist. DBCC PAGE gibt Ihnen diese Information als Teil seines Headers.

DBArgenis
quelle
3
Widerwillig gebe ich Ihnen "die Antwort", @DBArgenis. Ich behaupte immer noch, dass dies DBCC PAGEein schrecklicher Weg ist, etwas zu finden, aber Sie scheinen richtig zu sein. Es ist schade, dass die Daten von DBCC PAGEquasi Kauderwelsch sind und sich nicht auf eine reale Systemzeit beziehen.
Jeremiah Peschka
8
Ein Beispiel wäre eine nützliche Ergänzung zu dieser Antwort.
Mark Storey-Smith
3
@ MarkStorey-Smith - da stimme ich zu. Wenn DBArgenis keinen Trick im Ärmel hat, kann ich nicht erkennen, wie nützlich das ist.
Martin Smith
2
Kein Verweis auf DBCC PAGE ist jemals etwas Nützliches.
Jeremiah Peschka