SQL ServerでLRU-K値を表示することはできますか?


21

SQL Server sys.dm_os_memory_cache_entriesでは、キャッシュ内のエントリの元のコストとキャッシュエントリの現在のコスト(original_costおよびcurrent_costそれぞれ)の両方を表示できます。DMVにsys.dm_os_buffer_descriptorsは、現在メモリ内にあるページのレコードと、ページに関するメタデータが含まれています。DVMで利用できない興味深い情報の1つは、データページのLRU-K値です。

SQL ServerのバッファプールのデータページのLRU-K値を取得することは可能ですか?もしそうなら、どのように?


これはバージョン固有ですか?
JNK

1
@JNK-完璧な世界ではありませんが、SQL Server 2012で動作する限り、心配する必要はありません。
ジェレミアペシュカ

回答:


21

私が見る限り、実際にこれを行う便利な方法はありません。

他の答えは言及DBCC PAGEし、詳細を理解するために読者に任せます。実験から私はそれらが意味すると仮定しますbUse1

これDBCC PAGEは、それ自体がページの使用であるアカウントを考慮に入れず、値は表示されるに更新されます。

これを示すスクリプトを以下に示します(実行に12秒かかります)。

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

典型的な結果は

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

2番目の結果は

+---------+-------------------------+--------------+--------------------+
| 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 |
+---------+-------------------------+--------------+--------------------+

7秒の遅延後の出力は7増加し、5秒の遅延後は5増加します。

したがって、これらのLRU値はエポックからの秒数であることは明らかです。SQL Serverサービスを再起動してもエポックは変わりませんが、マシンを再起動すると変わります。

値は65,536秒ごとにロールオーバーするので、次のようなものを使用すると推測します system_up_time mod 65536

これにより、未回答の質問が1つ残ります(受験者はいますか?)。SQL Serverは、内部ブックに従ってLRU-Kwithを使用しますK=2。あるべきではないbUse2?もしそうなら、それはどこですか?

bUse1値を変更せずに監視する方法は1つありますが、これはボブワードがここで示しています。

デバッガーをSQL Serverプロセスに接続し、バッファー構造のメモリアドレスの参照先メモリを表示します(上図0x00000002FE1F1440参照)。

上記のスクリプトを実行した直後にこれを行い、次のことを確認しました。

ここに画像の説明を入力してください

(以前の実験から、強調表示されたバイトが実行間で変更された唯一のものであることがわかったので、これらは間違いなく正しいものです)。

1つの驚くべき側面はSELECT CAST(0xc896 as int)= 51350です。

これは、によって報告されるよりも正確に3600(1時間)少なくなりDBCC PAGEます。

これは、DBCC PAGE自分自身を呼び出すことでページをキャッシュに保存することを嫌う試みだと思います。「通常の」ページの場合、この1時間の調整は選択されません。走った後

SELECT *
FROM T

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

メモリに表示される値は予想どおりです。

DBCCコマンドは、実際にはその倍の値を更新します。に一度

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

高い値で再び

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

下のもので。

私はDBCC BUFFER/ を使用せずにページのバッファアドレスを取得する方法を知りませんDBCC PAGEが、これらの両方を使用すると、検査しようとしている値が変更されます!


3
まあ、これはあなたのクリスマスを過ごす1つの方法です。:-)
RBarryYoung

3
@RBarryYoung BeatsがTrivial Pursuitをプレイしています!
マーティンスミス

デバッガを適切に使用するためにボーナスポイントを与えることができれば、私はそうします。
ジェレマイアペシュカ

1
よくやった!(そして優れたデバッグスキル!)
DBArgenis

@DBArgenis-ありがとう!残念なことに、実際的な解決策はないようです。これを簡単に確認できれば、非常に有益です。
マーティンスミス

8

ツイッターでペシュカ氏に言及したように、この情報はメモリ内のページを保持するBUF構造に保持されます。DBCC PAGEは、ヘッダーの一部としてこの情報を提供します。


3
残念なことに、私はあなたに「答え」を与えます、@ DBArgenis。私はまだそれDBCC PAGEが何かを見つけるひどい方法だと主張していますが、あなたは正しいようです。からのデータDBCC PAGEが事実上意味不明であり、実際のシステム時間に関連していないのは残念です。
ジェレマイアペシュカ

8
例は、この答えへの便利な追加です。
マークストーリースミス

3
@ MarkStorey-Smith-同意します。DBArgenisが巧妙な仕掛けをしていない限り、これがどのように役立つかはわかりません。
マーティンスミス

2
DBCC PAGEへの参照が有用なものになることはありません。
ジェレマイアペシュカ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.