监测谁用了SQL Server的Tempdb空间
转自:http://blogs.msdn.com/b/apgcdsd/archive/2011/02/11/sql-server-tempdb.aspx
Tempdb 系统数据库是一个全局资源,供连接到 SQL Server 实例的所有用户使用。在现在的SQL Server里,其使用频率可能会超过用户的想象。如果Tempdb空间耗尽,许多操作将不能完成。
作为一个支持工程师,会被经常问到象“我的Tempdb为什么这么大?”“是谁把我的Tempdb空间用完的?”在SQL 2000的时候,这个问题很难回答。好在SQL 2005以后,引入了一张新的管理视图:sys.dm_db_file_space_usage。通过查询这张视图,能了解tempdb的空间使用情况,能知道tempdb的空间是被哪一块对象使用掉的,是用户对象(user_object_reserved_page_count字段),还是系统对象(internal_object_reserved_page_count字段),还是版本存储区(version_store_reserved_page_count字段)。
在讨论Tempdb空间使用之前,我们先简单介绍一下通常什么操作会大量使用Tempdb。在SQL 2005和SQL 2008里,使用Tempdb空间的远远不止是临时表。常见的使用对象有:
用户对象(user_object_reserved_page_count)
用户对象由用户显式创建。这些对象可以位于用户会话的作用域中,也可位于创建对象所用例程的作用域中。 可以是存储过程、触发器或用户定义函数。 用户对象可以是下列项之一:
- 用户定义的表和索引
- 系统表和索引
- 全局临时表和索引
- 局部临时表和索引
- table 变量
- 表值函数中返回的表
内部对象(internal_object_reserved_page_count)
内部对象是根据需要由 SQL Server 数据库引擎创建的,用于处理 SQL Server 语句。 内部对象可以在语句的作用域中创建和删除。 内部对象可以是下列项之一:
- 用于游标。
- 用于哈希联接或哈希聚合操作的查询。
- 某些 GROUP BY、ORDER BY 或 UNION 查询的中间排序结果。
版本存储(version_store_reserved_page_count)
版本存储区主要用来支持Snapshot事务隔离级别,以及SQL 2005以后推出的一些其他提高数据库并发度的新功能。
由此可见,光从用户发过来的语句本身,是很难判断这个连接的操作是否会使用Tempdb的。一个典型的例子,就是某些查询。如果表格上有良好的索引做支持,SQL Server不需要做哈希联接(Hash Join),那这个查询就不会用Tempdb。反之,如果表格很大,又没有好的索引,那Tempdb使用量就可能不小。
tempdb空间使用的一大特点,是只有一部分对象,例如用户创建的临时表、table变量等,可以用sys.allocation_units和 sys.partitions这样的管理视图来管理。许多内部对象和版本存储在这些管理视图里没有体现。所以,sp_spaceused的结果和真实使用会有很大差异,tempdb的空间使用是不能用sp_spaceused来跟踪的。必须借助sys.dm_db_file_space_usage这样的管理视图和管理函数,才能看到全貌。
下面以一个实例,讨论一下如何用DBCC命令、管理视图(DMV)以及管理函数(DMF)来监视是什么语句正在使用tempdb。
为了使结果简单,我们在测试之前先把SQL Server重起一次。
然后我们在Management Studio里做一个连接(连接A),将下面语句输入。这些语句会使用tempdb的空间。
select @@spid
go
use adventureworks
go
select getdate()
go
select * into #mySalesOrderDetail
from Sales.SalesOrderDetail
-- 创建一个temp table
-- 这个操作应该会申请user objects page
go
waitfor delay '0:0:2'
select getdate()
go
drop table #mySalesOrderDetail
-- 删除一个temp table
-- 这个操作后user object page数量应该会下降
go
waitfor delay '0:0:2'
select getdate()
go
select top 100000 * from
[Sales].[SalesOrderDetail]
INNER JOIN [Sales].[SalesOrderHeader]
ON [Sales].[SalesOrderHeader] .[SalesOrderID] = [Sales].[SalesOrderHeader].[SalesOrderID];
-- 这里做了一个比较大的join.
-- 应该会有internal objects的申请.
go
select getdate()
-- join 语句做完以后internal objects page数目应该下降
go
那用什么脚本可用监视上面的行为呢?下面的脚本就可以监视和发现当前的Tempdb使用者。这个脚本需要在使用tempdb的语句开始运行之前开始。(读者当然可以根据自己的喜好,修改这个脚本。)
脚本首先用“dbcc showfilestats”语句查询当前tempdb的总体使用量。再查询sys.dm_db_file_space_usage视图,得到Tempdb里当前总共有多少用户对象、内部对象、以及版本存储。然后查询sys.dm_db_session_space_usage和sys.dm_exec_sessions,找到当前使用Tempdb的所有连接。最后通过sys.dm_exec_sql_text,找到这些连接正在运行的语句。
use tempdb
-- 每隔1秒钟运行一次,直到用户手工终止脚本运行
while 1=1
begin
select getdate()
-- 从文件级看tempdb使用情况
dbcc showfilestats
-- Query 1
-- 返回所有做过空间申请的session信息
Select 'Tempdb' as DB, getdate() as Time,
SUM (user_object_reserved_page_count)*8 as user_objects_kb,
SUM (internal_object_reserved_page_count)*8 as internal_objects_kb,
SUM (version_store_reserved_page_count)*8 as version_store_kb,
SUM (unallocated_extent_page_count)*8 as freespace_kb
From sys.dm_db_file_space_usage
Where database_id = 2
-- Query 2
-- 这个管理视图能够反映当时tempdb空间的总体分配
SELECT t1.session_id,
t1.internal_objects_alloc_page_count, t1.user_objects_alloc_page_count,
t1.internal_objects_dealloc_page_count , t1.user_objects_dealloc_page_count,
t3.*
from sys.dm_db_session_space_usage t1 ,
-- 反映每个session累计空间申请
sys.dm_exec_sessions as t3
-- 每个session的信息
where
t1.session_id = t3.session_id
and (t1.internal_objects_alloc_page_count>0
or t1.user_objects_alloc_page_count >0
or t1.internal_objects_dealloc_page_count>0
or t1.user_objects_dealloc_page_count>0)
-- Query 3
-- 返回正在运行并且做过空间申请的session正在运行的语句
SELECT t1.session_id,
st.text
from sys.dm_db_session_space_usage as t1,
sys.dm_exec_requests as t4
CROSS APPLY sys.dm_exec_sql_text(t4.sql_handle) AS st
where t1.session_id = t4.session_id
and t1.session_id >50
and (t1.internal_objects_alloc_page_count>0
or t1.user_objects_alloc_page_count >0
or t1.internal_objects_dealloc_page_count>0
or t1.user_objects_dealloc_page_count>0)
waitfor delay '0:0:1'
end

图1
在运行这个脚本的连接(连接B)里(图1),我们选择好“Result to File”。先开始运行它,指定输出文件路径。然后,我们再运行连接A(图2)。连接A运行结束后,手工停止连接B的运行。

图2
在连接A的结果中(),可以得到四个时间。图片上的例子,是:
11:39:36.513 -- 开始创建temp table
11:39:38.920 – 开始删除temp table
11:39:40.937 – 开始查询
11:39:45.733 – 查询结束
连接B生成的是一个文本文件。利用一些有“列出所有包含某个特定字符串”行功能的编辑器工具,可以把每个命令结果挑出来。
从连接B生成的文本文件里所有dbcc showfilestats的结果(图3),可以看出tempdb的使用空间有过两次增长(从23到210,从47到118),中间有一次下降(从210到47)。

图3
从连接B生成的文本文件里所有Query 1的结果(图3),我们可以看到有三段时间,user object和internal object空间有申请和释放动作。它们分别是11:39:36 – 11:39:37 (user_objects_kb增长),11:39:40 – 11:39:41 (user_objects_kb下降),11:39:40 – 11:39:43(internal_objects_kb增长)。

图4
从Query 2的结果(图4)可以看到Connection A在这三个时间段都处于运行状态。

图5
根据时间,可以从Query 3的结果(图5)里找到Connection A当时正在运行的语句。例如在11:39:40 – 11:39:43(internal_objects_kb增长)这段时间里,一直都在运行下面这句话:

图6
从上面的结果可以看出,连接A的语句中,用tempdb最多的时间点在11:39:41和11:39:42之间,连接正在做图6里面的那条查询语句。SQL Server需要空间存放一些内部对象,来完成Inner Join。
监测谁用了SQL Server的Tempdb空间的更多相关文章
- [转]如何监测谁用了SQL Server的Tempdb空间
Tempdb 系统数据库是一个全局资源,供连接到 SQL Server 实例的所有用户使用.在现在的SQL Server里,其使用频率可能会超过用户的想象.如果Tempdb空间耗尽,许多操作将不能完成 ...
- SQL Server中tempdb的管理
原文:SQL Server中tempdb的管理 资料来自: http://blogs.msdn.com/b/sqlserverstorageengine/archive/tags/tempdb/ ht ...
- SQL Server中TempDB管理(version store的逻辑结构)
原文:SQL Server中TempDB管理(version store的逻辑结构) 原文来自: http://blogs.msdn.com/b/sqlserverstorageengine/arch ...
- SQL Server中TempDB管理(版本存储区的一个example)
原文:SQL Server中TempDB管理(版本存储区的一个example) 原文来自: http://blogs.msdn.com/b/sqlserverstorageengine/archive ...
- SQL Server中tempdb的management
对<SQL Server中tempdb的management>的一些更正和补充 对<SQL Server中tempdb的management>的一些更正和补充 前几天看了这 ...
- 对《SQL Server中tempdb的management》的一些更正和补充
对<SQL Server中tempdb的management>的一些更正和补充 前几天看了这篇文章:SQL Server中tempdb的management 发现里面有些内容不是很准确 文 ...
- sql server转移tempdb数据库的物理存放位置
转移前将原来的文件备份一下 将 tempdb 从其在磁盘上的当前位置移动到其他磁盘位置.由于每次启动 MSSQLSERVER 服务时都会重新创建 tempdb,因此不需要从物理意义上移动数据和日志 ...
- —教训深刻—SQL Server大约TempDB使用
场景现象 中午查询了流水,因未与业务人员沟通好.忘了删选条件,导致TempDB不能分配空间,SQL Server高负载执行. 错误分析 我们来看看错误日志: 再来看看TempDB自增长记录: 事件 逻 ...
- 结合谷歌地图多边形(polygon)与Sql Server 2008的空间数据类型计算某个点是否在多边形内的注意事项
首先在利用 GEOGRAPHY::STPolyFromText(@GeoStr, 4326) 这样的函数把字符串转换为Geography类型时,字符串里经纬度的顺序是 “经度[空格]纬度”,即“lon ...
随机推荐
- POJ 3630 Phone List Trie题解
Trie的应用题目. 本题有两个难点了: 1 动态建立Trie会超时,须要静态建立数组,然后构造树 2 推断的时候注意两种情况: 1) Tire树有133,然后插入13333556的时候.2)插入顺序 ...
- 广东省-IT红黑榜排名公司名称
红榜Top100 Order Company Name Point Change 1 百富计算机技术(深圳)有限公司 94.00 -- 2 中国网通广州分公司 88.00 -- 3 深圳市汇 ...
- wxWidgets刚開始学习的人导引(1)——前言
wxWidgets刚開始学习的人导引全文件夹 PDF版及附件下载 1 前言2 下载.安装wxWidgets3 wxWidgets应用程序初体验4 wxWidgets学习资料及利用方法指导5 用wx ...
- 一个Jquery特效(转)
见证花开!!码上有花 先看效果 尝试点击,IE9+ 画心 清空 ... 请自由点击画布 创意来自于网络 可搜搜[程序员表白] 看上去像是[当耐特]的作品的加工版本 代码 当然要自己写了 能力有限, ...
- [Windows]_[0基础]_[使用命令行工具dumpbin分析文件]
dumpbin(vs拥有) 1. 出口lib函数符号文件(symbols) dumpbin /exports zlib1.lib Microsoft (R) COFF/PE Dumper Versio ...
- 解决 下载 CM-12.0 源代码出现 Fatal: duplicate project .....问题
在使用 repo init -u git://github.com/CyanogenMod/android.git -b cm-12.0 初始化代码库的时候出现如下错误: fatal: manifes ...
- SSH证书登录方式(无password验证登录)
经常在工作中须要在各个Linux机间进行跳转,每次password的输入成了麻烦,并且也不安全.在实际使用中,在windows下常使用secureCRT工具或teraterm工具进行SSH登录.以及实 ...
- UVA 11248 - Frequency Hopping(网络流量)
UVA 11248 - Frequency Hopping 题目链接 题意:给定一个网络,如今须要从1到N运输流量C,问是否可能,假设可能输出可能,假设不可能,再问能否通过扩大一条边的容量使得可能,假 ...
- Linux高性能server规划——多线程编程(在)
多线程编程 Linux主题概述 线程模型 线程是程序中完毕一个独立任务的完整执行序列.即一个可调度的实体. 依据执行环境和调度者的身份.线程可分为内核线程和用户线程.内核线程,在有的系统上也称为LWP ...
- Xcode 凝视代码
#pragma mark ---------------凝视信息-------------------- -(void)RequestSP { // MARK: 凝视信息 // TODO: 凝视信息 ...