SQLserver 的性能排查笔记

SQLserver 的性能排查笔记
查看存储中用到的文本

SELECT DISTINCT
OBJECT_NAME(id),id from syscomments with(nolock)
where id in
( select object_id(name) from dbo.sysobjects with(nolock) where xtype='P'
)
and text like '%内容%' 

运行中的语句

--运行中的语句
SELECT
	individual_query=SUBSTRING(qt.text,(er.statement_start_offset/2)+1,((CASE  WHEN  er.statement_end_offset=-1 THEN  LEN(CONVERT(NVARCHAR(MAX),qt.text))* 2 ELSE   er.statement_end_offset  END-er.statement_start_offset)/2)+1),
    parent_query=qt.text,
    es.session_id,
    database_name=DB_NAME(er.database_id),
    er.cpu_time,
    er.reads,
    er.writes,
    er.logical_reads,
    login_name,
    er.status,
    blocking_session_id,
    wait_type,
    wait_resource,
    wait_time,
    program_name,
    host_name,
    nt_domain,
    start_time,
   -- DATEDIFF(MS,er.start_time,GETDATE())as duration,
    (SELECT  query_plan  FROM  sys.dm_exec_query_plan (er.plan_handle))AS  query_plan
FROM
    sys.dm_exec_requests er
    INNER  JOIN  sys.dm_exec_sessions  es  ON er.session_id=es.session_id
    CROSS  APPLY  sys.dm_exec_sql_text (er.sql_handle)AS  qt
WHERE
    es.session_id> 50         
    AND  es.session_Id  NOT  IN(@@SPID)
ORDER BY
    1, 2

当前CPU最大的语句

SELECT TOP 100 s.session_id,
           r.status,
           r.cpu_time,
           r.logical_reads,
           r.reads,
           r.writes,
           r.total_elapsed_time / (1000 * 60) 'Elaps M',
           SUBSTRING(st.TEXT, (r.statement_start_offset / 2) + 1,
           ((CASE r.statement_end_offset
                WHEN -1 THEN DATALENGTH(st.TEXT)
                ELSE r.statement_end_offset
            END - r.statement_start_offset) / 2) + 1) AS statement_text,
           COALESCE(QUOTENAME(DB_NAME(st.dbid)) + N'.' + QUOTENAME(OBJECT_SCHEMA_NAME(st.objectid, st.dbid))
           + N'.' + QUOTENAME(OBJECT_NAME(st.objectid, st.dbid)), '') AS command_text,
           r.command,
           s.login_name,
           s.host_name,
           c.client_net_address,
           s.program_name,
           s.last_request_end_time,
           s.login_time,
           r.open_transaction_count
FROM sys.dm_exec_connections c
JOIN sys.dm_exec_sessions s ON c.session_id= s.session_id
JOIN sys.dm_exec_requests r ON r.session_id = s.session_id CROSS APPLY sys.Dm_exec_sql_text(r.sql_handle) AS st
-- WHERE r.session_id != @@SPID
ORDER BY r.cpu_time DESC

历史CPU最大的语句

SELECT TOP 100 st.text AS batch_text,
    SUBSTRING(st.TEXT, (qs.statement_start_offset / 2) + 1,
    ((CASE qs.statement_end_offset WHEN - 1 THEN DATALENGTH(st.TEXT) ELSE qs.statement_end_offset END - qs.statement_start_offset) / 2) + 1) AS statement_text,
    qs.execution_count,
    qs.total_worker_time,
    qs.last_execution_time,
    (qs.total_worker_time / 1000) / qs.execution_count AS avg_cpu_time_ms,
    (qs.total_elapsed_time / 1000) / qs.execution_count AS avg_elapsed_time_ms,
    qs.total_logical_reads / qs.execution_count AS avg_logical_reads,
    (qs.total_worker_time / 1000) AS cumulative_cpu_time_all_executions_ms,
    (qs.total_elapsed_time / 1000) AS cumulative_elapsed_time_all_executions_ms
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(sql_handle) st
ORDER BY(qs.total_worker_time / qs.execution_count) DESC

索引创建建议

SELECT CONVERT(VARCHAR(30), GETDATE(), 126) AS runtime,
    mig.index_group_handle,
    mid.index_handle,
    CONVERT(DECIMAL(28, 1), migs.avg_total_user_cost * migs.avg_user_impact * (migs.user_seeks + migs.user_scans)) AS improvement_measure,
    'CREATE INDEX missing_index_' + CONVERT(VARCHAR, mig.index_group_handle) + '_' + CONVERT(VARCHAR, mid.index_handle) + ' ON ' + mid.statement + ' (' + ISNULL(mid.equality_columns,
        '') + CASE WHEN mid.equality_columns IS NOT NULL
AND mid.inequality_columns IS NOT NULL THEN ','
ELSE ''
END + ISNULL(mid.inequality_columns,
        '') + ')' + ISNULL(' INCLUDE (' + mid.included_columns + ')',
        '') AS create_index_statement,
    migs.*,
    mid.database_id,
    mid.[object_id]
FROM sys.dm_db_missing_index_groups mig
INNER JOIN sys.dm_db_missing_index_group_stats migs ON migs.group_handle = mig.index_group_handle
INNER JOIN sys.dm_db_missing_index_details mid ON mig.index_handle = mid.index_handle
WHERE CONVERT (DECIMAL (28, 1),
               migs.avg_total_user_cost * migs.avg_user_impact * (migs.user_seeks + migs.user_scans)) > 10
ORDER BY migs.avg_total_user_cost * migs.avg_user_impact * (migs.user_seeks + migs.user_scans) DESC

索引

--查看索引
dbcc ShowContig('tableName')
--重建索引
dbcc dbreindex('tableName')

查看死锁

SELECT XEventData.XEvent.value('@timestamp', 'datetime2(3)'),  
cast(XEventData.XEvent.value('(data/value)[1]', 'varchar(max)') as xml) 
FROM (SELECT CAST (target_data AS XML) AS TargetData     
FROM sys.dm_xe_session_targets st     
JOIN sys.dm_xe_sessions s 
ON s.address = st.event_session_address     
WHERE [name] = 'system_health' AND st.target_name = N'ring_buffer') AS Data 
CROSS APPLY TargetData.nodes ('//RingBufferTarget/event') AS XEventData (XEvent)     
WHERE XEventData.XEvent.value('@name', 'varchar(4000)') = 'xml_deadlock_report';

查看阻塞

select * from master..sysprocesses where blocked<>0

查看临时表占用大小

select cast(sum(a.total_pages)*8/1024 as varchar)+' MB' total     
from sys.partitions p 
join sys.allocation_units a 
on p.partition_id = a.container_id 
join sys.tables it 
on p.object_id = it.object_id
 where it.name like 'TMP%' 

查询系统中每个临时表占用的空间大小统计

select it.name, cast(sum(a.total_pages)*8 as varchar)+'KB' total     
from sys.partitions p 
join sys.allocation_units a 
on p.partition_id = a.container_id  
join sys.tables it 
on p.object_id = it.object_id 
where it.name like 'tm%' 
group by  it.name order by sum(a.total_pages)*8 desc

查看所有已经标记为需要删除的临时表

select name
from sys.tables u 
join T_BAS_TEMPORARYTABLENAME v 
on u.name=v.FTABLENAME 
and (v.FPROCESSTYPE=1 or v.FCREATEDATE<GETDATE()-1); 

删除所有已经标记为需要删除的临时表

declare @sql as varchar(max) 
set @sql='' 
select @sql=@sql+'drop table '+name+';' 
from sys.tables u 
join T_BAS_TEMPORARYTABLENAME v 
on u.name=v.FTABLENAME 
and (v.FPROCESSTYPE=1 or v.FCREATEDATE<GETDATE()-1); 
exec(@sql); 
delete u from T_BAS_TEMPORARYTABLENAME u where  
not exists(select 1 from sys.tables where u.ftablename=name ); 

查询字段长度

SELECT a.name,b.name,c.DATA_TYPE,b.max_length FROM sys.tables a join sys.columns b on b.object_id = a.object_id
join INFORMATION_SCHEMA.COLUMNS c on b.name=c.COLUMN_NAME and a.name=c.TABLE_NAME
where a.name='表名' AND B.NAME = '字段名'

PLE (Page Life Expectancy, 页面的预期寿命)

SELECT object_name, counter_name, cntr_value
FROM sys.dm_os_performance_counters
WHERE object_name LIKE '%Manager%'
AND counter_name = 'Page life expectancy'

一般在300以上

执行时间

--SELECT TOP 10 * FROM T_BD_MATERIAL

SELECT top 100
(total_elapsed_time / execution_count)/1000 N'平均时间ms'
,total_elapsed_time/1000 N'总花费时间ms'
,total_worker_time/1000 N'所用的CPU总时间ms'
,total_physical_reads N'物理读取总次数'
,total_logical_reads/execution_count N'每次逻辑读次数'
,total_logical_reads N'逻辑读取总次数'
,total_logical_writes N'逻辑写入总次数'
,execution_count N'执行次数'
,creation_time N'语句编译时间'
,last_execution_time N'上次执行时间'
,SUBSTRING(
st.text,
(qs.statement_start_offset/2) + 1,
(
(CASE statement_end_offset WHEN -1 THEN DATALENGTH(st.text) ELSE qs.statement_end_offset END - qs.statement_start_offset)/2
) + 1
) N'执行语句'
,qp.query_plan
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st
CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp
WHERE
SUBSTRING(
st.text,
(qs.statement_start_offset/2) + 1,
(
(CASE statement_end_offset WHEN -1 THEN DATALENGTH(st.text) ELSE qs.statement_end_offset END - qs.statement_start_offset)/2
) + 1
) not like '%fetch%'
ORDER BY last_execution_time DESC,total_elapsed_time / execution_count DESC;

卡慢排查

--打开IO和TIME统计开关
SET STATISTICS TIME ON
SET  STATISTICS IO ON

--清空缓存
checkpoint
DBCC DROPCLEANBUFFERS 
DBCC FREEPROCCACHE     

--数据库连接情况
select * from sys.dm_exec_connections
select client_net_address,count(*) from sys.dm_exec_connections group by client_net_address

--获取SQL Server允许同时用户连接的最大数
SELECT @@MAX_CONNECTIONS 

--获取当前SQL服务器所有的连接详细信息
SELECT * FROM sysprocesses 

查看被锁的表

select request_session_id spid,OBJECT_NAME(resource_associated_entity_id) tableName
from sys.dm_tran_locks where resource_type='OBJECT';

# 这时会出现两列数据
第一列 --spid 锁表进程
第二列 --tableName 被锁表名

对锁表进行解锁

declare @spid int
Set @spid = 57 --锁表进程
declare @sql varchar(1000)
set @sql='kill '+cast(@spid as varchar)
exec(@sql)

查看所有的spid

select blocked
from (select * from sysprocesses where blocked>0 ) a
where not exists(select * from (select * from sysprocesses where blocked>0 ) b
where a.blocked=spid)
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值