首页 > 代码库 > tempdb文件写远远大于读,内存不断飙升问题
tempdb文件写远远大于读,内存不断飙升问题
最近忽然碰到了一台数据库服务器磁盘IO升高一倍多,内存增长很快。cpu正常,网络流量正常,明显不是有人在拉数据。就想着分析看看。最终找到了原因。记录下分析过程。
1、用dbcc showfilestats 查看文件空间分配情况;用sp_lock和sp_who查看是否有死锁情况。
2、用select * from tempdb..sysobjects where xtype=‘U‘ 查看tempdb里有哪些对象。带1个#的表是无法查看表数据的,带##的是全局临时表是可以查看表数据的。
3、运行下面的脚本得到逻辑写次数比较多的sql语句。
SELECT TOP 1000
ST.text AS ‘执行的SQL语句‘,
QS.execution_count AS ‘执行次数‘,
QS.total_elapsed_time AS ‘耗时‘,
QS.total_logical_reads AS ‘逻辑读取次数‘,
QS.total_logical_writes AS ‘逻辑写入次数‘,
QS.total_physical_reads AS ‘物理读取次数‘,
QS.creation_time AS ‘执行时间‘ ,
QS.*
FROM sys.dm_exec_query_stats QS
CROSS APPLY
sys.dm_exec_sql_text(QS.sql_handle) ST
WHERE QS.creation_time BETWEEN ‘2017-01-19 00:00:00‘ AND ‘2017-01-19 14:00:00‘
ORDER BY
QS.total_logical_writes DESC
4、另外这里有微软官方关于这个问题的解决文档:
https://blogs.msdn.microsoft.com/apgcdsd/2011/02/10/sql-servertempdb/
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 =244
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:1:0‘
end
select count(*)*8/1024 as ‘cachesize(MB)‘,
db_name(database_id) ‘database‘
from sys.dm_os_buffer_descriptors
group by db_name(database_id),database_id
order by ‘cachesize(MB)‘ desc
6、通过以上语句的运行及仔细分析,最终找到是有一个功能需要随机显示十条数据,结果被写成了每次从数据库里通过n张表的join取出1000条数据并把每列通过case when转换后返回,程序在这1000条返回的数据里挑选十条数据显示。只要用户刷新几次,这个sql的效率就测出来了。
7、第一次碰到这种问题,记录下来,以便参考。很多时候貌似什么都会(委托、多线程、泛型),但是忽略了这些基本的性能,sql随便乱写,最终只会导致写出来的功能经不起时间和网站流量的考验,功能回炉改造是唯一出路。
tempdb文件写远远大于读,内存不断飙升问题