É possível exibir valores LRU-K no SQL Server?

21

No SQL Server sys.dm_os_memory_cache_entries, é possível visualizar o custo original de uma entrada no cache, bem como o custo atual da entrada no cache ( original_coste current_costrespectivamente). A DMV sys.dm_os_buffer_descriptorscontém um registro das páginas que estão atualmente na memória, além de alguns metadados sobre as páginas. Uma parte interessante das informações não disponíveis no DVM são os valores LRU-K para as páginas de dados.

É possível obter os valores LRU-K para páginas de dados no buffer pool no SQL Server? Se sim, como?

Jeremiah Peschka
fonte
Esta versão é específica?
JNK 03/12
1
@JNK - Em um mundo perfeito, não, mas desde que funcione no SQL Server 2012, não me preocupo.
Jeremiah Peschka

Respostas:

21

De fato, não há maneira útil de fazer isso, tanto quanto eu possa ver.

A outra resposta menciona DBCC PAGEe deixa ao leitor descobrir os detalhes. Por experimentação, presumo que eles significam bUse1.

Isso não leva em conta o DBCC PAGEuso da página e o valor é atualizado antes de ser mostrado para nós.

Um script demonstrando isso está abaixo (leva 12 segundos para ser executado).

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

Resultados típicos são

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

Com o segundo resultado sendo

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

A saída após o atraso de 7 segundos é incrementada em 7 e após o atraso de 5 segundos em 5.

Portanto, parece claro que esses valores de LRU são segundos desde alguma época. Reiniciar o serviço SQL Server não altera a época, mas reiniciar a máquina.

O valor passa a cada 65.536 segundos, então presumo que ele use algo como system_up_time mod 65536

Isso deixa uma pergunta sem resposta em minha mente (alguém que faz perguntas?). O SQL Server usa LRU-Kcom de K=2acordo com o livro interno. Não deveria haver um bUse2? Se sim, onde é isso?

Há uma maneira de observar o bUse1valor sem alterá-lo que eu conheço e que é demonstrado por Bob Ward aqui.

Anexe um depurador ao processo do SQL Server e exiba a memória referenciada para o endereço de memória da estrutura do buffer (mostrado 0x00000002FE1F1440acima).

Fiz isso imediatamente após executar o script acima e vi o seguinte.

insira a descrição da imagem aqui

(De experiências anteriores, eu achei que os bytes destacados eram os únicos que mudavam entre as execuções, então esses são definitivamente os corretos).

Um aspecto surpreendente é que SELECT CAST(0xc896 as int)= 51350.

Isso é exatamente 3600 (uma hora) menos que o relatado por DBCC PAGE.

Acredito que essa seja uma tentativa de desfavorecer as páginas mantidas em cache, chamando a DBCC PAGEsi mesma. Para uma página "normal", selecione este ajuste de uma hora não ocorre. Depois de correr

SELECT *
FROM T

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

O valor mostrado na memória é como esperado.

O DBCCcomando atualiza esse valor duas vezes. Uma vez em

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

Com o valor mais alto, novamente em

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

Com o inferior.

Não conheço nenhuma maneira de obter endereços de buffer para páginas sem usar DBCC BUFFER/ de DBCC PAGEnenhuma maneira e usar essas duas alterações no valor que estamos tentando inspecionar!

Martin Smith
fonte
3
Bem, esta é uma maneira de passar o seu Natal. :-)
RBarryYoung
3
@RBarryYoung Beats tocando Trivial Pursuit!
Martin Smith
Se eu pudesse dar pontos de bônus pelo uso apropriado de um depurador, eu daria.
Jeremiah Peschka
1
Bem feito! (E grandes habilidades de depuração!)
DBArgenis
@DBArgenis - Thanks! Pena que não parece haver uma solução prática. Pode ser bastante informativo se pudermos ver isso facilmente.
Martin Smith
8

Como mencionei ao Sr. Peschka no twitter, essas informações são mantidas na estrutura do BUF que mantém a página na memória. A página DBCC fornece essas informações como parte de seu cabeçalho.

DBArgenis
fonte
3
De má vontade, concedo a você "a resposta", @DBArgenis. Ainda afirmo que DBCC PAGEé uma maneira terrível de encontrar qualquer coisa, mas você parece estar correto. É uma pena que os dados DBCC PAGEsejam, efetivamente, sem sentido e não estejam relacionados a nenhum tempo real do sistema.
Jeremiah Peschka
8
Um exemplo seria uma adição útil a esta resposta.
Mark-Storey-Smith #
3
@ MarkStorey-Smith - eu concordo. A menos que o DBArgenis tenha algum truque na manga, não vejo como isso é útil.
Martin Smith
2
Nenhuma referência à DBCC PAGE chega a ser útil.
Jeremiah Peschka