在执行任何查询时,SQL Server都会将数据读取到内存,数据使用之后,不会立即释放,而是会缓存在内存Buffer中,当再次执行相同的查询时,如果所需数据全部缓存在内存中,那么SQL Server不会产生Disk IO操作,立即返回查询结果,这是SQL Server的性能优化机制。 一,主要的内存消费者(Memory Consumer) 1,数据缓存(Data Cache)
Data Cache是存储数据页(Data Page)的缓冲区,当SQL Server需要读取数据文件(File)中的数据页(Data Page)时,SQL Server会把整个Page都调入内存(内存中的一个Page叫做buffer),Page是数据访问的最小单元。
当用户修改了某个Page上的数据时,SQL Server 会先在内存中修改Buffer,但是不会立即将这个数据叶写回硬盘,而是等到CheckPoint或lazy Writer进程运行时集中处理。当用户读取某个Page后,如果SQL Server没有内存压力,它不会在内存中删除这个Page,因为内存中的数据页始终存放着数据的最新状态,如果有其他用户使用这个Page,SQL Server 不需要从硬盘中读取一次,节省语句执行的时间。理想情况是SQL Server将用户需要访问的所有数据都缓存在内存中,SQL Server 永远不需要去硬盘读取数据,只需要在CheckPoint 或 lazy Write运行时把修改过的页面写回硬盘即可 2,查询计划缓存(Query Plan Cache)
存储查询语句和存储过程的执行计划,以供重用,而不需要重新编译(Compile),因为编译查询语句产生执行计划是一个非常耗费资源的过程。 二,查看内存消耗
在SQL Server中,只有内存书记员(Memory Clerk)能够分配内存,Memory Clerk会记录已经分配内存的数量,任何一个需要使用内存的对象,必须创建自己的Memory Clerk,并使用该Memory clerk来分配内存。 1,查看Memory clerk分配的内存量
select memory_node_id,
type,
pages_kb,
virtual_memory_reserved_kb,
virtual_memory_committed_kb,
shared_memory_reserved_kb,
shared_memory_committed_kb,
page_size_in_bytes
from sys.dm_os_memory_clerks
where type = 'MEMORYCLERK_SQLQERESERVATIONS'
对于内存结点64,只在DAC中使用。 2,统计Memory Clerk分配的内存总量
select mc.type,mc.name,
sum(mc.pages_kb) as AllocatedPages_KB,
sum(mc.virtual_memory_reserved_kb) as VM_Reserved_KB,
sum(mc.virtual_memory_committed_kb) as VM_Committed_KB,
--sum(mc.shared_memory_reserved_kb) as ShareMem_Reserved_KB,
--sum(mc.shared_memory_committed_kb) as ShareMem_Committed_KB,
max(mc.page_size_in_bytes)/1024 as SinglePageSize_KB
from sys.dm_os_memory_clerks mc
group by mc.type,mc.name
order by AllocatedPages_KB desc,mc.type,mc.name
select DB_NAME(bd.database_id) as dbname,
OBJECT_NAME(p.object_id) as ObjectName,
i.name as IndexName,
count(0) as BufferCounts,
sum(bd.free_space_in_bytes)/1024 as TotalFreeSpace_KB,
cast(sum(bd.free_space_in_bytes)/(8*1024.0)/count(0) as decimal(10,4))*100 as FreeSpaceRatio,
sum(cast(bd.is_modified as int)) as TotalDirtyPages,
sum(bd.row_count) as TotalRowCounts
from sys.allocation_units au
inner join sys.dm_os_buffer_descriptors bd
on au.allocation_unit_id=bd.allocation_unit_id
inner join sys.partitions p
on au.container_id=p.hobt_id
inner join sys.indexes i
on p.object_id=i.object_id and p.index_id=p.index_id
inner join sys.objects o
on p.object_id=o.object_id
where bd.database_id=DB_ID(N'database_name')
and o.type<>N'S'
group by bd.database_id,p.object_id,i.name
order by BufferCounts desc,dbname,ObjectName
select cp.objtype,cp.cacheobjtype,
sum(cp.size_in_bytes) as TotalSize_B,
COUNT(cp.bucketid) as CacheCounts,
sum(cp.refcounts) as TotalRefCounts,
sum(cp.usecounts) as TotalUseCounts
from sys.dm_exec_cached_plans cp
group by cp.objtype,cp.cacheobjtype
order by TotalSize_B desc