Have you ever wondered why DBCC CHECKDB, for instance, doesn’t flush the buffer pool when it runs on a database that is larger than the memory capacity of the server?
There’s cool mechanism that it uses called disfavoring. When a buffer is no longer required, the buffer can be marked as the least recently used of all the buffers in the buffer pool, meaning that it will used next when the buffer pool needs a new buffer to read a page from disk. This means that a small number of buffers will be used repeatedly instead of filling the buffer pool with pages from the database being consistency checked.
This mechanism isn’t anything to do with DBCC, but DBCC makes good use of it. DBCC CHECK* commands, DBCC SHOWCONTIG, DBCC UPDATEUSAGE, and the sys.dm_db_index_physical_stats DMV (which is really part of DBCC) all use this.
Let me show you…
On our fast test machine at home (rack-mounted Dell R720) I’ve got a 500GB database called AdventureWorks_Big residing on four Fusion-io SSDs. First off I’ll show you the table I’m going to use:
SELECT [page_count] FROM sys.dm_db_index_physical_stats ( DB_ID (), OBJECT_ID (N'Production.TransactionHistoryEnlarged'), 1, NULL, N'LIMITED'); GO
page_count ----------- 18114867
It’s more than 138GB, and my buffer pool is 56,000MB. Now I’ll make sure the buffer pool is empty, and then run DBCC CHECKTABLE on that table:
DBCC DROPCLEANBUFFERS; GO DBCC CHECKTABLE (N'Production.TransactionHistoryEnlarged') WITH NO_INFOMSGS; GO
Five minutes later it completes. But how much of the table did it read into the buffer pool?
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
DatabaseName DirtyPageCount CleanPageCount DirtyPageMB CleanPageMB ------------------- -------------- -------------- ----------- ----------- AdventureWorks_Big 0 188 0 1 master 3 77 0 0 model 0 32 0 0 msdb 1 39 0 0 Resource Database 0 24 0 0 tempdb 260 179 2 1
Cool eh?
There are some other places that disfavor buffers when they’re done with them, including:
- During redo of log records, if a page already has a log record’s effects on it and so doesn’t need to be changed
- During bulk load into a heap
- Large table scans that are more than 10% of the buffer pool size will disfavor pages instead of forcing pages from other databases to be flushed from memory
And backups don’t use the buffer pool at all so they’re not going to cause buffer pool flushing either.
You can watch disfavoring happening for table scans using the leaf_page_disfavored Extended Event.
Bottom line – some of your common maintenance activities don’t damage the buffer pool, which is a good thing.
5 Responses to Buffer pool disfavoring
I’m pretty sure it was originally put in specifically for the large scan case (15-16 year old design discussions now attempting to be retrieved from my brain’s archival storage), so it will be rather interesting if you can’t reproduce it. There has to be some mechanism for keeping scans from polluting the buffer pool.
Now there’s a blast from the past – good to hear from you Hal! Indeed – I can see the disfavoring happening but I don’t see the expected behavior in the contents of the buffer pool. I’m sure there’s something I’m missing as I’ve repro’d the behavior before when I was back on the team, but I can’t remember exactly what I did. I have a PFE buddy checking it out (if only I had code access still!) and I’ll repro as soon as I figure it out. I have a simple parallel clustered index scan in 2012 SP1 that will happily flush the bpool every time. Cheers.
This could be useful in an OLTP environment that has one off reports that run occasionally. I’m guessing there is no way to manually force disfavoring?
No way to force it, but it should happen naturally in the right circumstances. I’ll blog as soon as I figure it out.
[...] [...]