Here’s an interesting question that came up in our IEPTO1 class in Chicago this week (paraphrasing):
I was doing a demo recently where I was demonstrating physical I/Os occurring. I used DBCC DROPCLEANBUFFERS, then enabled SET STATISTICS IO ON and performed a SELECT operation. I was expecting to see physical reads occurring but I only saw logical reads. What’s going on? Why weren’t there any physical reads after I’d flushed the buffer pool with DBCC DROPCLEANBUFFERS?
It’s a very interesting question. If you ask most people what DBCC DROPCLEANBUFFERS does, you’ll get the response that it clears out the buffer pool (as my student expected).
But it doesn’t.
It drops *clean* pages from the buffer pool only.
A clean page is one that has not been changed since it was read into memory or last written to disk. A dirty page is one that has not been written to disk since it was last changed. Dirty pages are not dropped by DBCC DROPCLEANBUFFERS, they are only made clean by writing them to disk (either through one of the various kinds of checkpoints or by the lazy writer – or one of the per-NUMA node lazy writers if you have NUMA configured).
The demo in question had updated the table being selected, and so when DBCC DROPCLEANBUFFERS was executed, the pages from that table remained in memory – hence no physical reads were required for the subsequent SELECT.
If you want to ensure that all pages from a database are flushed from memory, you need to first perform a manual CHECKPOINT of that database and then run DBCC DROPCLEANBUFFERS.
You can then verify that there are no pages in memory for the database in question using the following code:
SELECT *, [DirtyPageCount] * 8 / 1024 AS [DirtyPageMB], [CleanPageCount] * 8 / 1024 AS [CleanPageMB] FROM (SELECT (CASE WHEN ([database_id] = 32767) THEN N'Resource Database' ELSE DB_NAME ([database_id]) END) AS [DatabaseName], SUM (CASE WHEN ([is_modified] = 1) THEN 1 ELSE 0 END) AS [DirtyPageCount], SUM (CASE WHEN ([is_modified] = 1) THEN 0 ELSE 1 END) AS [CleanPageCount] FROM sys.dm_os_buffer_descriptors GROUP BY [database_id]) AS [buffers] ORDER BY [DatabaseName] GO
Hope this helps some of you out there!
7 thoughts on “When DBCC DROPCLEANBUFFERS doesn’t work…”
Paul, thanks for the above info.
I have issued a checkpoint and DBCC DROPCLEANBUFFERS and pulled the result set from your query, it did show couple of dirty pages from master and tempdb. Questions is: When I run your query after few min with absolutely no activity on the server, why is it still showing some clean pages count for all the DB’s on the server.
Thanks,
System table pages and allocation bitmaps.
Thanks Paul.
How to clear out the buffer pool for a specific db?
DBCC FLUSHPROCINDB
I was doing a demo on implicit conversions and had the same question. I am doing a simple select statement, no data modifications and yet I still get logical reads even after issuing a checkpoint.
CHECKPOINT
DBCC FREEPROCCACHE
DBCC DROPCLEANBUFFERS
DECLARE @LastName NVARCHAR(50)
SET @LastName = ‘LNAME1082055’
SET STATISTICS IO ON
SET STATISTICS TIME ON
SELECT LastName, Salary FROM Employee WHERE LastName = @LastName
SET STATISTICS IO OFF
SET STATISTICS TIME OFF
Are there bookmark/key lookups in the plan? Is this a heap? Is it in tempdb? Any of these would cause logical reads.