分离/附加或脱机/在线是否清除特定数据库的缓冲区高速缓存?


8

今天,我的一个伙伴告诉我,除了启动SQL Server之外,我还可以简单地分离并重新附加数据库,此操作将从缓存中清除给定数据库的页面和计划。我不同意并在下面提供证据。如果您不同意我的意见或有更好的反驳,则绝对不要提供。

我在此版本的SQL Server上使用AdventureWorks2012:

选择@@ VERSION;
Microsoft SQL Server 2012-11.0.2100.60(X64)
Windows NT 6.1(内部版本7601:Service Pack 1)上的Developer Edition(64位)

加载数据库后,我运行以下查询:

首先,运行在此处找到的乔纳森·K的AW育肥脚本:

AW发胖

---------------------------
-步骤1:Bpool Stuff?
---------------------------
USE [AdventureWorks2012];
走

选择
     OBJECT_NAME(p.object_id)AS [ObjectName]
   ,p.object_id
   ,p.index_id
   ,COUNT(*)/ 128 AS [缓冲区大小(MB)]
   ,COUNT(*)AS [buffer_count]
从
     sys.allocation_units AS a
     内联接sys.dm_os_buffer_descriptors AS b
           开启a.allocation_unit_id = b.allocation_unit_id
     内部联接系统分区AS p
           开启a.container_id = p.hobt_id
哪里
     b.database_id = DB_ID()
     AND p.object_id> 100
通过...分组
     p.object_id
   ,p.index_id
订购
     buffer_count DESC;

结果显示在这里: 在此处输入图片说明

分离并重新附加数据库,然后重新运行查询。

---------------------------
-步骤2:分离/固定
---------------------------
-分离
USE [主人]
走
EXEC master.dbo.sp_detach_db @dbname = N'AdventureWorks2012'
走

-附上
USE [master];
走

创建数据库[AdventureWorks2012] 
( 
    FILENAME = N'C:\ sql server \ files \ AdventureWorks2012_Data.mdf' 
)
    ,
( 
    FILENAME = N'C:\ sql server \ files \ AdventureWorks2012_Log.ldf' 
)
 附加;
走

现在,bpool中有什么?

---------------------------
-步骤3:Bpool Stuff?
---------------------------
USE [AdventureWorks2012];
走

选择
     OBJECT_NAME(p.object_id)AS [ObjectName]
   ,p.object_id
   ,p.index_id
   ,COUNT(*)/ 128 AS [缓冲区大小(MB)]
   ,COUNT(*)AS [buffer_count]
从
     sys.allocation_units AS a
     内联接sys.dm_os_buffer_descriptors AS b
           开启a.allocation_unit_id = b.allocation_unit_id
     内部联接系统分区AS p
           开启a.container_id = p.hobt_id
哪里
     b.database_id = DB_ID()
     AND p.object_id> 100
通过...分组
     p.object_id
   ,p.index_id
订购
     buffer_count DESC;

结果: 在此处输入图片说明

此时所有读取是否合乎逻辑?

--------------------------------
-步骤4:逻辑只读?
--------------------------------
USE [AdventureWorks2012];
走

将统计信息IO设置为ON;   
    SELECT * FROM DatabaseLog;
    走
将统计信息设置为“关闭”;  

/ *
(受影响的1597行)
表“ DatabaseLog”。扫描计数1,逻辑读782,物理读0,预读768,lob逻辑读94,lob物理读4,lob预读24。
* /  

我们可以看到,缓冲池并没有被分离/连接完全吹走。好像我的朋友错了。是否有人不同意或有更好的论据?

另一种选择是使数据库脱机然后再联机。让我们尝试一下。

--------------------------------
-步骤5:离线/在线?
--------------------------------
ALTER DATABASE [AdventureWorks2012]设置离线;
走
ALTER DATABASE [AdventureWorks2012]设置在线;
走

---------------------------
-步骤6:Bpool Stuff?
---------------------------
USE [AdventureWorks2012];
走

选择
     OBJECT_NAME(p.object_id)AS [ObjectName]
   ,p.object_id
   ,p.index_id
   ,COUNT(*)/ 128 AS [缓冲区大小(MB)]
   ,COUNT(*)AS [buffer_count]
从
     sys.allocation_units AS a
     内联接sys.dm_os_buffer_descriptors AS b
           开启a.allocation_unit_id = b.allocation_unit_id
     内部联接系统分区AS p
           开启a.container_id = p.hobt_id
哪里
     b.database_id = DB_ID()
     AND p.object_id> 100
通过...分组
     p.object_id
   ,p.index_id
订购
     buffer_count DESC;

看来离线/在线操作要好得多。

在此处输入图片说明

Answers:


9

我最初以为您在这里做些什么。一直沿用的工作假设是,缓冲池可能没有立即刷新,因为它需要“一些工作”才能完成,为什么还要麻烦直到需要内存。但...

您的测试有缺陷。

您在缓冲池中看到的是重新连接数据库后读取的页面,而不是数据库先前实例的剩余页面。

我们可以看到,缓冲池并没有被分离/连接完全吹走。好像我的朋友错了。是否有人不同意或有更好的论据?

是。您的physical reads 0意思是说没有任何实体读物

表“ DatabaseLog”。扫描计数1,逻辑读782,物理读0,预读768,lob逻辑读94,lob物理读4,lob预读24。

Craig Freedman的博客中所述,顺序预读机制试图确保在查询处理器请求页面之前将其保存在内存中,这就是为什么您看到零或比预期的物理读取计数低的原因。

当SQL Server对大表执行顺序扫描时,存储引擎将启动预读机制,以确保页面在内存中并且可以在查询处理器需要它们之前进行扫描。预读机制尝试使扫描前保留500页。

在满足预查询要求之前,没有任何页面在内存中。

至于为什么联机/脱机导致不同的缓冲池配置文件,需要进行更多闲置调查的原因。@MarkSRasmussen下次下次访问时也许可以帮助我们。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.