SQLServer:Memory Manager:Target Server Memory(KB):服务器可供SQL Server使用的内存量。一般是由SQL Server能访问到的内存量和SQL Server的sp_Configure配置中的Max Server Memory值中的较小值算得。
SQLServer:Memory Manger:Memory Grants Pending:等待内存授权的进程总数。如果该值不为0,说明当前有用户的内存申请由于内存压力被延迟,这意味着比较严重的内存瓶颈。
SQLServer:Buffer Manager:Buffer Cache Hit Ratio:数据从缓冲区中找到而不需要从硬盘中去取的百分比。SQL Server在运行一段时间后,该比率的变化应该很小,而且都应该在98%以上,如果在95%以下,说明有内存不足的问题。
SQLServer:Buffer Manager:Lazy Writes/Sec:每秒钟被惰性编辑器(Lazy writer)写入的缓冲数。当SQL Server感觉到内存压力的时候,会将最久没有使用的数据页面和执行计划从缓冲池中清理掉,做这个动作的就是Lazy Writer。 Page Life Expectancy:页面不被引用后,在缓冲池中停留的秒数。在内存没有压力的情况下,页面会一直待在缓冲池中,Page Life Expectancy会维持在一个比较高的值,如果有内存压力时,Page Life Expectancy会下降。所以如果Page Life Expectancy不能维持在一个值上,就代表SQLServer有内存瓶颈。
SQLServer:Buffer Manager:Database Pages :就是Database Cache的大小。 SQLServer:Buffer Manager:Free Pages:SQL Server中空闲可用的大小。
SQLServer:Buffer Manager:Stolen Pages:Buffer Pool中Stolen的大小。
SQLServer:Buffer Manager:Total Pages:Buffer Pool的总大小(等于Database Pages+Free Pages+Stolen Pages)。该值乘以8KB,应该等于Memory Manager:Total Server Memory的值。
从上面这些计数器中我们就能了解SQL Server的内存使用情况,结合前面说的系统层的计数器大概能看出是否存在内存瓶颈。 2)内存动态管理视图
在SQL Server 2005以后,SQL Server的内存管理是使用Memory Clerk的方式统一管理。所有的SQL Server的内存的申请或释放,都需要通过它们的Clerk,SQL Server也通过这些Clerk的协调来满足不同需求。通过查询这些DMV,可以得到比用性能计数器更加详细的内存使用情况。
我们可以通过下面的查询语句来检测SQL Server的Clerk的内存使用情况。
使用sys.dm_os_memory_clerks查看内存使用情况
SELECT type, --Clerk的类型
sum(virtual_memory_reserved_kb) as vm_Reserved_kb, -- 保留的内存
sum(virtual_memory_committed_kb) as vm_Committed_kb, --提交的内存
sum(awe_allocated_kb) as awe_Allocated_kb, -- 开启AWE后使用的内存
sum(shared_memory_reserved_kb) as sm_Reserved_kb, -- 共享的保留内存
sum(shared_memory_committed_kb) as sm_Committed_kb, -- 共享的提交内存
sum(single_pages_kb) as SinlgePage_kb, -- Buffer Pool中的Stolen的内存
sum(multi_pages_kb) as MultiPage_kb -- MemToLeave的内存
FROM sys.dm_os_memory_clerks
GROUP BY type
ORDER BY type 从上面的查询语句,我们可以算出前面提到的内存大小
declare @name nvarchar(100)
declare @cmd nvarchar(1000)
declare dbnames cursor for
select name from master.dbo.sysdatabases
open dbnames
fetch next from dbnames into @name
while @@fetch_status = 0
begin
set @cmd = 'select b.database_id, db=db_name(b.database_id),p.object_id,p.index_id,buffer_count=count(*) from '
--这里的object_id代表是SQL Server中的对象号,index_id代表是索引号,buffer_count代表的是页面数
+ @name + '.sys.allocation_units a, '
+ @name + '.sys.dm_os_buffer_descriptors b, ' + @name + '.sys.partitions p
where a.allocation_unit_id = b.allocation_unit_id
and a.container_id = p.hobt_id
and b.database_id = db_id(''' + @name + ''')
group by b.database_id,p.object_id, p.index_id
order by b.database_id, buffer_count desc'
exec (@cmd)
fetch next from dbnames into @name
end
close dbnames
deallocate dbnames
go
-- 根据上面取出来的@object_id找出是哪个数据库的哪个表
SELECT s.name AS table_schema, o.name as table_name --使用的就是table_schema.table_name表
FROM sys.sysobjects AS o INNER JOIN
sys.schemas AS s ON o.uid = s.schema_id
WHERE (o.id = @object_id)
-- 根据上面取出来的@object_id和@index_id找出索引的名称
SELECT id, indid, name as index_name -- index_name就是索引的名称
FROM sys.sysindexes
WHERE (id = @object_id) AND (indid = @index_id)
-- 根据上面取出来的表名table_schema.table_name和索引的名称index_name,还可以找出该索引是建立在哪些字段上的
EXEC sp_helpindex 'table_schema.table_name'
查看内存中缓存的执行计划,以及执行计划对应的语句:
-- 输出可能较大,请小心使用
SELECT usecounts, refcounts, size_in_bytes, cacheobjtype, objtype, text
FROM sys.dm_exec_cached_plans cp CROSS APPLY sys.dm_exec_sql_text(plan_handle)
ORDER BY objtype DESC