是否可以在 SQL Server 中查看 LRU-K 值?

Jer*_*hka 21 sql-server

在 SQL Server 的 中sys.dm_os_memory_cache_entries,既可以查看缓存中条目的原始成本,也可以查看缓存条目的当前成本(original_costcurrent_cost)。DMVsys.dm_os_buffer_descriptors包含当前内存中页面的记录以及有关页面的一些元数据。DVM 中没有的一大块有趣的信息是数据页的 LRU-K 值。

是否可以获取 SQL Server 缓冲池中数据页的 LRU-K 值?如果是这样,如何?

Mar*_*ith 23

事实上,据我所知,没有任何有用的方法可以做到这一点。

另一个答案提到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
Run Code Online (Sandbox Code Playgroud)

典型的结果是

+----+--------------+-------------------------+-------+-------------+
| ID | ParentObject |         Object          | Field | ObjectValue |
+----+--------------+-------------------------+-------+-------------+
|  8 | BUFFER:      | BUF @0x00000002FE1F1440 | bUse1 |       54938 |
| 49 | BUFFER:      | BUF @0x00000002FE1F1440 | bUse1 |       54945 |
| 90 | BUFFER:      | BUF @0x00000002FE1F1440 | bUse1 |       54950 |
+----+--------------+-------------------------+-------+-------------+
Run Code Online (Sandbox Code Playgroud)

第二个结果是

+---------+-------------------------+--------------+--------------------+
| 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 |
+---------+-------------------------+--------------+--------------------+
Run Code Online (Sandbox Code Playgroud)

7 秒延迟后的输出增加 7,5 秒延迟后的输出增加 5。

所以很明显,这些 LRU 值是自某个纪元以来的秒数。重新启动 SQL Server 服务不会改变时代,但重新启动机器会改变。

该值每 65,536 秒滚动一次,所以我认为它只是使用类似 system_up_time mod 65536

这确实在我的脑海中留下了一个悬而未决的问题(任何接受者?)。SQL Server使用LRU-KK=2根据内部书。不应该有bUse2吗?如果是,那是哪里?

bUse1我知道有一种观察值而不改变它的方法,Bob Ward在这里演示了这一点。

将调试器附加到 SQL Server 进程并显示缓冲区结构的内存地址的引用内存(如上所示0x00000002FE1F1440)。

我在运行上面的脚本后立即执行此操作并看到以下内容。

在此处输入图片说明

(从之前的实验中,我发现突出显示的字节是唯一在运行之间发生变化的字节,因此这些绝对是正确的)。

一个令人惊讶的方面是SELECT CAST(0xc896 as int)= 51350

这正好比 报告的少 3600(一小时)DBCC PAGE

我相信这是通过调用DBCC PAGE自身来不赞成将页面保存在缓存中的一些尝试。对于“正常”页面,选择此一小时调整不会发生。运行后

SELECT *
FROM T

SELECT ((ms_ticks) % 65536000) / 1000 AS [Roughly Expected Value]
FROM sys.dm_os_sys_info
Run Code Online (Sandbox Code Playgroud)

内存中显示的值符合预期。

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
Run Code Online (Sandbox Code Playgroud)

使用更高的值然后再次在

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

与较低的。

我不知道有什么方法可以在不使用DBCC BUFFER/DBCC PAGE任何方式的情况下获取页面的缓冲区地址,但使用这两种方法都会更改我们试图检查的值!


小智 8

正如我在 Twitter 上对 Peschka 先生提到的,这些信息保存在将页面保存在内存中的 BUF 结构中。DBCC PAGE 将此信息作为其标题的一部分提供给您。