Um amigo meu me disse hoje que, em vez de pular o SQL Server, eu poderia simplesmente desanexar e reanexar um banco de dados e essa ação limparia as páginas e os planos do banco de dados fornecidos do cache. Eu discordei e forneço minhas evidências abaixo. Se você discorda de mim ou tem uma refutação melhor, por favor, forneça-a.
Estou usando o AdventureWorks2012 nesta versão do SQL Server:
SELECIONE @@VERSÃO; Microsoft SQL Server 2012 - 11.0.2100.60 (X64) Developer Edition (64 bits) no Windows NT 6.1 (Build 7601: Service Pack 1)
Tendo carregado o banco de dados, executo a seguinte consulta:
Em primeiro lugar, execute o script de engorda AW de Jonathan K encontrado aqui:
---------------------- -- Passo 1: Coisas de Bpool? ---------------------- USE [AdventureWorks2012]; VAI SELECIONE OBJECT_NAME(p.object_id) AS [ObjectName] , p.object_id , p.index_id , COUNT(*) / 128 AS [tamanho do buffer (MB)] , COUNT(*) AS [buffer_count] A PARTIR DE sys.allocation_units AS um INNER JOIN sys.dm_os_buffer_descriptors AS b ON a.allocation_unit_id = b.allocation_unit_id INNER JOIN sys.partitions AS p ON a.container_id = p.hobt_id ONDE b.database_id = DB_ID() E p.object_id > 100 GRUPO POR p.object_id , p.index_id ORDENAR POR buffer_count DESC;
O resultado é mostrado aqui:
Desanexe e anexe novamente o banco de dados e, em seguida, execute novamente a consulta.
---------------------- -- Etapa 2: desanexar/anexar ---------------------- -- Destacar USE [mestre] VAI EXEC master.dbo.sp_detach_db @dbname = N'AdventureWorks2012' VAI -- Anexar USE [mestre]; VAI CRIAR BANCO DE DADOS [AdventureWorks2012] ON ( FILENAME = N'C:\sql server\files\AdventureWorks2012_Data.mdf' ) , ( FILENAME = N'C:\sql server\files\AdventureWorks2012_Log.ldf' ) PARA ANEXO; VAI
O que está no bpool agora?
---------------------- -- Passo 3: Coisas de Bpool? ---------------------- USE [AdventureWorks2012]; VAI SELECIONE OBJECT_NAME(p.object_id) AS [ObjectName] , p.object_id , p.index_id , COUNT(*) / 128 AS [tamanho do buffer (MB)] , COUNT(*) AS [buffer_count] A PARTIR DE sys.allocation_units AS um INNER JOIN sys.dm_os_buffer_descriptors AS b ON a.allocation_unit_id = b.allocation_unit_id INNER JOIN sys.partitions AS p ON a.container_id = p.hobt_id ONDE b.database_id = DB_ID() E p.object_id > 100 GRUPO POR p.object_id , p.index_id ORDENAR POR buffer_count DESC;
E o resultado:
Todas as leituras são lógicas neste ponto?
-------------------------------- -- Etapa 4: somente leituras lógicas? -------------------------------- USE [AdventureWorks2012]; VAI DEFINIR ESTATÍSTICA IO ON; SELECIONE * DE DatabaseLog; VAI DEFINIR ESTATÍSTICA IO OFF; /* (1597 linhas afetadas) Tabela 'DatabaseLog'. Contagem de varredura 1, leituras lógicas 782, leituras físicas 0, leituras antecipadas 768, leituras lógicas lob 94, leituras físicas lob 4, leituras antecipadas lob 24. */
E podemos ver que o buffer pool não foi totalmente destruído pelo desanexar/anexar. Parece que meu amigo estava errado. Alguém discorda ou tem um argumento melhor?
Outra opção é off-line e, em seguida, on-line do banco de dados. Vamos tentar isso.
-------------------------------- -- Passo 5: Offline/Online? -------------------------------- ALTER DATABASE [AdventureWorks2012] DEFINIR OFFLINE; VAI ALTER DATABASE [AdventureWorks2012] DEFINIDO ONLINE; VAI ---------------------- -- Passo 6: Coisas de Bpool? ---------------------- USE [AdventureWorks2012]; VAI SELECIONE OBJECT_NAME(p.object_id) AS [ObjectName] , p.object_id , p.index_id , COUNT(*) / 128 AS [tamanho do buffer (MB)] , COUNT(*) AS [buffer_count] A PARTIR DE sys.allocation_units AS um INNER JOIN sys.dm_os_buffer_descriptors AS b ON a.allocation_unit_id = b.allocation_unit_id INNER JOIN sys.partitions AS p ON a.container_id = p.hobt_id ONDE b.database_id = DB_ID() E p.object_id > 100 GRUPO POR p.object_id , p.index_id ORDENAR POR buffer_count DESC;
Parece que a operação offline/online funcionou muito melhor.
Eu inicialmente pensei que você estava em algo aqui. A suposição de trabalho foi na linha de que talvez o buffer pool não tenha sido liberado imediatamente, pois requer "algum trabalho" para fazê-lo e por que se preocupar até que a memória seja necessária. Mas...
Seu teste é falho.
O que você está vendo no buffer pool são as páginas lidas como resultado da reanexação do banco de dados, não os restos da instância anterior do banco de dados.
Sim. Você está interpretando
physical reads 0
como significando que não houve nenhuma leitura físicaConforme descrito no blog de Craig Freedman, o mecanismo sequencial de leitura antecipada tenta garantir que as páginas estejam na memória antes de serem solicitadas pelo processador de consultas, e é por isso que você vê zero ou uma contagem de leitura física abaixo do esperado relatada.
Nenhuma das páginas necessárias para satisfazer sua consulta estava na memória até que a leitura antecipada as colocasse lá.
Por que online/offline resulta em um perfil de pool de buffer diferente garante um pouco mais de investigação ociosa. @MarkSRasmussen pode nos ajudar com isso na próxima vez que ele nos visitar.