在SQL Server中sys.dm_os_memory_cache_entries
,可以查看缓存中条目的原始成本以及缓存条目的当前成本(original_cost
和current_cost
)。DMV sys.dm_os_buffer_descriptors
包含当前内存中页面的记录以及有关页面的一些元数据。DVM中没有的一个有趣的信息块是数据页的LRU-K值。
是否可以获取SQL Server缓冲池中数据页的LRU-K值?如果是这样,怎么办?
在SQL Server中sys.dm_os_memory_cache_entries
,可以查看缓存中条目的原始成本以及缓存条目的当前成本(original_cost
和current_cost
)。DMV sys.dm_os_buffer_descriptors
包含当前内存中页面的记录以及有关页面的一些元数据。DVM中没有的一个有趣的信息块是数据页的LRU-K值。
是否可以获取SQL Server缓冲池中数据页的LRU-K值?如果是这样,怎么办?
Answers:
据我所知,实际上没有任何有用的方法可以做到这一点。
另一个答案提到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 |
+----+--------------+-------------------------+-------+-------------+
第二个结果是
+---------+-------------------------+--------------+--------------------+
| 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
这确实在我的脑海中留下了一个未解决的问题(任何参与者?)。SQL Server使用LRU-K
与K=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
内存中显示的值符合预期。
该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
但是同时使用这两种更改,我们正在尝试检查的值!
正如我在推特上向Peschka先生提到的那样,此信息保留在将页面保存在内存中的BUF结构中。DBCC PAGE将此信息作为标题提供给您。
DBCC PAGE
是找到任何东西的可怕方法,但是您似乎是正确的。很遗憾,来自的数据DBCC PAGE
实际上是乱码,并且与任何实际系统时间都不相关。