已经不再使用的表为什么数据页还在SQLServer的内存缓存中

1. 问题发现

  在学习内存调优时,使用如下代码,查询目前内存缓冲区中生产数据库的每个对象缓存页计数

  

SELECT count(*)AS cached_pages_count 
    ,name ,index_id 
FROM sys.dm_os_buffer_descriptors AS bd 
    INNER JOIN 
    (
        SELECT object_name(object_id) AS name 
            ,index_id ,allocation_unit_id
        FROM sys.allocation_units AS au
            INNER JOIN sys.partitions AS p 
                ON au.container_id = p.hobt_id 
                    AND (au.type = 1 OR au.type = 3)
        UNION ALL
        SELECT object_name(object_id) AS name   
            ,index_id, allocation_unit_id
        FROM sys.allocation_units AS au
            INNER JOIN sys.partitions AS p 
                ON au.container_id = p.partition_id 
                    AND au.type = 2
    ) AS obj 
        ON bd.allocation_unit_id = obj.allocation_unit_id
WHERE database_id = db_id()
GROUP BY name, index_id 
ORDER BY cached_pages_count DESC;

  发现前段应用程序已经不再使用的表,数据页缓存数排在首位,而且页数非常之多。这张表是之前用来作为数据统计分析的计算报表,后来上了数据仓库以及BI系统后,这张表就废弃掉了。但为什么内存中还是缓存这么多数据页?现在系统的内存并非是足够大,大到可以缓存整个数据库的数据页面,所以,感觉这些不再使用的数据页面应该被置换出内存

2.问题分析

  为了验证这种表的使用情况,使用如下语句查询表的索引使用情况

SELECT *  
FROM sys.dm_db_index_usage_stats ddius 
WHERE ddius.object_id = OBJECT_ID('t_rpt_office_shop_data')

  发现索引的user_scan 等确实为0,代表自上次服务启动以来,应用程序没用提交过对这个表的查询。

  但发现system_scan不为0,而且last_system_scan的日期为凌晨。

  所以猜想是不是凌晨的数据库维护计划中有导致system_scan的操作

  继续查看维护计划,发现果真有一个任务--更新统计信息任务,而且扫描类型是完全扫描

3.问题原因

  所以,问题是由每天早上的更新统计信息任务造成,因为执行完全扫描,相当于每天凌晨对这个表执行了一次全表扫描,此时会将数据页加载到内存缓冲区中。而且我发现凌晨这段时间内存的页面生命周期基本接近为0,估计也是这个造成的。

4.问题处理

  以下是我的处理方式,大家指正下~

  1. 将维护计划中的更新统计信息步骤删除掉,第二天发现内存缓冲的对象数据页计数基本和预测一致。
  2. 将不在使用的表进行数据压缩,减少磁盘空间的占用

 

 

    

原文地址:https://www.cnblogs.com/JentleWang/p/3617280.html