SQL常用性能相关脚本

--查询当前的事务



select 

t2.session_id as SPID,

t2.transaction_id,

transaction_begin_time,

N'已执行'+ltrim(datediff(mi,transaction_begin_time,getdate()))+N'分钟' as mi,

case transaction_type 

when 1 then N'读/写事务' 

when 2 then N'只读事务' 

when 3 then N'系统事务' 

when 4 then N'分布式事务' end tran_Type,

case transaction_state

when 0 then N'事务尚未完全初始化'

when 1 then N'事务已初始化但尚未启动'

when 2 then N'事务处于活动状态'

when 3 then N'事务已结束。该状态用于只读事务'

when 4 then N'已对分布式事务启动提交进程'

when 5 then N'事务处于准备就绪状态且等待解析'

when 6 then N'事务已提交'

when 7 then N'事务正在被回滚'

when 0 then N'事务已回滚'

end transaction_state,

client_net_address,

client_tcp_port,

program_name,

t2.text



from

sys.dm_tran_active_transactions t1 join (

select 

a.session_id,

transaction_id,

client_net_address,

client_tcp_port,

text,c.program_name

from sys.dm_tran_session_transactions a join (

select session_id,a2.text,client_net_address,client_tcp_port from sys.dm_exec_connections a1

cross apply sys.dm_exec_sql_text(a1.most_recent_sql_Handle) a2

) b on a.session_id=b.session_id

left join sys.dm_exec_sessions c on a.session_id=c.session_id

where is_user_transaction=1

)t2 on t1.transaction_ID=t2.transaction_ID

ORDER BY t2.transaction_id
View Code
 
   

 

--死锁相关,转自http://www.blogjava.net/parable-myth/archive/2007/10/15/153010.html

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[p_lockinfo]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)

drop procedure [dbo].[p_lockinfo]

GO



SET QUOTED_IDENTIFIER ON 

GO

SET ANSI_NULLS ON 

GO





/*--处理死锁



 查看当前进程,或死锁进程,并能自动杀掉死进程



 因为是针对死的,所以如果有死锁进程,只能查看死锁进程

 当然,你可以通过参数控制,不管有没有死锁,都只查看死锁进程



 感谢: caiyunxia,jiangopen 两位提供的参考信息



--邹建 2004.4--*/



/*--调用示例



 exec p_lockinfo

--*/
create proc p_lockinfo

@kill_lock_spid bit=1,  --是否杀掉死锁的进程,1 杀掉, 0 仅显示

@show_spid_if_nolock bit=1 --如果没有死锁的进程,是否显示正常进程信息,1 显示,0 不显示

as

declare @count int,@s nvarchar(1000),@i int

select id=identity(int,1,1),标志,

 进程ID=spid,线程ID=kpid,块进程ID=blocked,数据库ID=dbid,

 数据库名=db_name(dbid),用户ID=uid,用户名=loginame,累计CPU时间=cpu,

 登陆时间=login_time,打开事务数=open_tran, 进程状态=status,

 工作站名=hostname,应用程序名=program_name,工作站进程ID=hostprocess,

 域名=nt_domain,网卡地址=net_address

into #t from(

 select 标志='死锁的进程',

  spid,kpid,a.blocked,dbid,uid,loginame,cpu,login_time,open_tran,

  status,hostname,program_name,hostprocess,nt_domain,net_address,

  s1=a.spid,s2=0

 from master..sysprocesses a join (

  select blocked from master..sysprocesses group by blocked

  )b on a.spid=b.blocked where a.blocked=0

 union all

 select '|_牺牲品_>',

  spid,kpid,blocked,dbid,uid,loginame,cpu,login_time,open_tran,

  status,hostname,program_name,hostprocess,nt_domain,net_address,

  s1=blocked,s2=1

 from master..sysprocesses a where blocked<>0

)a order by s1,s2



select @count=@@rowcount,@i=1



if @count=0 and @show_spid_if_nolock=1

begin

 insert #t

 select 标志='正常的进程',

  spid,kpid,blocked,dbid,db_name(dbid),uid,loginame,cpu,login_time,

  open_tran,status,hostname,program_name,hostprocess,nt_domain,net_address

 from master..sysprocesses

 set @count=@@rowcount

end



if @count>0

begin

 create table #t1(id int identity(1,1),a nvarchar(30),b Int,EventInfo nvarchar(255))

 if @kill_lock_spid=1

 begin

  declare @spid varchar(10),@标志 varchar(10)

  while @i<=@count

  begin

   select @spid=进程ID,@标志=标志 from #t where id=@i

   insert #t1 exec('dbcc inputbuffer('+@spid+')')

   if @标志='死锁的进程' exec('kill '+@spid)

   set @i=@i+1

  end

 end

 else

  while @i<=@count

  begin

   select @s='dbcc inputbuffer('+cast(进程ID as varchar)+')' from #t where id=@i

   insert #t1 exec(@s)

   set @i=@i+1

  end

 select a.*,进程的SQL语句=b.EventInfo

 from #t a join #t1 b on a.id=b.id

end



GO

SET QUOTED_IDENTIFIER OFF 

GO

SET ANSI_NULLS ON 

GO
View Code

 

----索引执行情况

SELECT objects.name ,

databases.name ,

indexes.name ,

user_seeks ,

user_scans ,

user_lookups ,

partition_stats.row_count

FROM sys.dm_db_index_usage_stats stats

LEFT JOIN sys.objects objects ON stats.object_id = objects.object_id

LEFT JOIN sys.databases databases ON databases.database_id = stats.database_id

LEFT JOIN sys.indexes indexes ON indexes.index_id = stats.index_id

AND stats.object_id = indexes.object_id

LEFT JOIN sys.dm_db_partition_stats partition_stats ON stats.object_id = partition_stats.object_id

AND indexes.index_id = partition_stats.index_id

WHERE 1 = 1

--AND databases.database_id = 7

AND objects.name IS NOT NULL

AND indexes.name IS NOT NULL

AND user_scans>0

ORDER BY user_scans DESC ,stats.object_id ,indexes.index_id
View Code
 
   
----最占用CPU

SELECT TOP 100 execution_count,

total_logical_reads /execution_count AS [Avg Logical Reads],

total_elapsed_time /execution_count AS [Avg Elapsed Time],

db_name(st.dbid) as [database name],

object_name(st.dbid) as [object name],

object_name(st.objectid) as [object name 1],

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) AS statement_text

FROM sys.dm_exec_query_stats AS qs CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS st

WHERE execution_count > 100 AND qs.creation_time > dateadd(day,-3,getdate())

ORDER BY 1 DESC;
View Code


---执行时间最长的命令



SELECT TOP 10 COALESCE(DB_NAME(st.dbid),

DB_NAME(CAST(pa.value as int))+'*','Resource') AS DBNAME,

SUBSTRING(text,

-- starting value for substring

CASE WHEN statement_start_offset = 0

OR statement_start_offset IS NULL

THEN 1

ELSE statement_start_offset/2 + 1 END,

-- ending value for substring

CASE WHEN statement_end_offset = 0

OR statement_end_offset = -1

OR statement_end_offset IS NULL

THEN LEN(text)

ELSE statement_end_offset/2 END -

CASE WHEN statement_start_offset = 0

OR statement_start_offset IS NULL

THEN 1

ELSE statement_start_offset/2 END + 1

) AS TSQL,

total_logical_reads/execution_count AS AVG_LOGICAL_READS

FROM sys.dm_exec_query_stats

CROSS APPLY sys.dm_exec_sql_text(sql_handle) st

OUTER APPLY sys.dm_exec_plan_attributes(plan_handle) pa

WHERE attribute = 'dbid'

ORDER BY AVG_LOGICAL_READS DESC ;
View Code
 
   
----缺索引



SELECT TOP 30

[Total Cost] = ROUND(avg_total_user_cost * avg_user_impact * (user_seeks + user_scans),0)

, avg_user_impact, TableName = statement, [EqualityUsage] = equality_columns

, [InequalityUsage] = inequality_columns, [Include Cloumns] = included_columns

FROM sys.dm_db_missing_index_groups g

INNER JOIN sys.dm_db_missing_index_group_stats s

ON s.group_handle = g.index_group_handle

INNER JOIN sys.dm_db_missing_index_details d

ON d.index_handle = g.index_handle

ORDER BY [Total Cost] DESC;
View Code
 
   

 

--经常更新却很少使用的索引

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 

SELECT 

DB_NAME() AS DatabaseName 

, SCHEMA_NAME(o.Schema_ID) AS SchemaName 

, OBJECT_NAME(s.[object_id]) AS TableName 

, i.name AS IndexName 

, s.user_updates 

, s.system_seeks + s.system_scans + s.system_lookups 

AS [System usage] 

INTO #TempUnusedIndexes 

FROM sys.dm_db_index_usage_stats s 

INNER JOIN sys.indexes i ON s.[object_id] = i.[object_id] 

AND s.index_id = i.index_id 

INNER JOIN sys.objects o ON i.object_id = O.object_id 

WHERE 1=2 

EXEC sp_MSForEachDB 'USE [?]; 

INSERT INTO #TempUnusedIndexes 

SELECT TOP 20 

DB_NAME() AS DatabaseName 

, SCHEMA_NAME(o.Schema_ID) AS SchemaName 

, OBJECT_NAME(s.[object_id]) AS TableName 

, i.name AS IndexName 

, s.user_updates 

, s.system_seeks + s.system_scans + s.system_lookups 

AS [System usage] 

FROM sys.dm_db_index_usage_stats s 

INNER JOIN sys.indexes i ON s.[object_id] = i.[object_id] 

AND s.index_id = i.index_id 

INNER JOIN sys.objects o ON i.object_id = O.object_id 

WHERE s.database_id = DB_ID() 

AND OBJECTPROPERTY(s.[object_id], ''IsMsShipped'') = 0 

AND s.user_seeks = 0 

AND s.user_scans = 0 

AND s.user_lookups = 0 

AND i.name IS NOT NULL 

ORDER BY s.user_updates DESC' 

SELECT TOP 20 * FROM #TempUnusedIndexes

WHERE DatabaseName = 'agilepoint50' ORDER BY [user_updates] DESC 

DROP TABLE #TempUnusedIndexes
View Code
 
   

 

---维护代价最高的索引

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 

SELECT 

DB_NAME() AS DatabaseName 

, SCHEMA_NAME(o.Schema_ID) AS SchemaName 

, OBJECT_NAME(s.[object_id]) AS TableName 

, i.name AS IndexName 

, (s.user_updates ) AS [update usage] 

, (s.user_seeks + s.user_scans + s.user_lookups) AS [Retrieval usage] 

, (s.user_updates) - 

(s.user_seeks + s.user_scans + s.user_lookups) AS [Maintenance cost] 

, s.system_seeks + s.system_scans + s.system_lookups AS [System usage] 

, s.last_user_seek 

, s.last_user_scan 

, s.last_user_lookup 

INTO #TempMaintenanceCost 

FROM sys.dm_db_index_usage_stats s 

INNER JOIN sys.indexes i ON s.[object_id] = i.[object_id] 

AND s.index_id = i.index_id 

INNER JOIN sys.objects o ON i.object_id = O.object_id 

WHERE 1=2 

EXEC sp_MSForEachDB 'USE [?]; 

INSERT INTO #TempMaintenanceCost 

SELECT TOP 20 

DB_NAME() AS DatabaseName 

, SCHEMA_NAME(o.Schema_ID) AS SchemaName 

, OBJECT_NAME(s.[object_id]) AS TableName 

, i.name AS IndexName 

, (s.user_updates ) AS [update usage] 

, (s.user_seeks + s.user_scans + s.user_lookups) 

AS [Retrieval usage] 

, (s.user_updates) - 

(s.user_seeks + user_scans + 

s.user_lookups) AS [Maintenance cost] 

, s.system_seeks + s.system_scans + s.system_lookups AS [System usage] 

, s.last_user_seek 

, s.last_user_scan 

, s.last_user_lookup 

FROM sys.dm_db_index_usage_stats s 

INNER JOIN sys.indexes i ON s.[object_id] = i.[object_id] 

AND s.index_id = i.index_id 

INNER JOIN sys.objects o ON i.object_id = O.object_id 

WHERE s.database_id = DB_ID() 

AND i.name IS NOT NULL 

AND OBJECTPROPERTY(s.[object_id], ''IsMsShipped'') = 0 

AND (s.user_seeks + s.user_scans + s.user_lookups) > 0 

ORDER BY [Maintenance cost] DESC' 

SELECT top 20 * FROM #TempMaintenanceCost WHERE DatabaseName ='agilepoint50' ORDER BY [Maintenance cost] DESC 

DROP TABLE #TempMaintenanceCost
View Code
 
   

 

---表及数据库的空间占用

set nocount on

declare @db varchar(20)

set @db = db_name()

dbcc updateusage(@db) with no_infomsgs

go



create table #tblspace

(



数据表名称 varchar(50) null,

记录笔数 int null,

保留空间 varchar(15) null,

数据使用空间 varchar(15) null,

索引使用空间 varchar(15) null,

未使用空间 varchar(15) null,



)

declare @tblname varchar(50)

declare curtbls cursor for

select table_name from information_schema.tables

where table_type = 'base table'

open curtbls

Fetch next from curtbls into @tblname

while @@fetch_status = 0

begin

insert #tblspace exec sp_spaceused @tblname

fetch next from curtbls into @tblname

end

close curtbls

deallocate curtbls



select * from #tblspace order by

convert(int,left(保留空间,len(保留空间)-2)) desc

drop table #tblspace
View Code
 
   

 

 
  

 --检测死锁

--如果发生死锁了,我们怎么去检测具体发生死锁的是哪条SQL语句或存储过程?

 --这时我们可以使用以下存储过程来检测,就可以查出引起死锁的进程和SQL语句。SQL Server自带的系统存储过程sp_who和sp_lock也可以用来查找阻塞和死锁, 但没有这里介绍的方法好用。

use master



go



create procedure sp_who_lock



as



begin



declare @spid int,@bl int,



 @intTransactionCountOnEntry  int,



        @intRowcount    int,



        @intCountProperties   int,



        @intCounter    int







 create table #tmp_lock_who (



 id int identity(1,1),



 spid smallint,



 bl smallint)



 



 IF @@ERROR<>0 RETURN @@ERROR



 



 insert into #tmp_lock_who(spid,bl) select  0 ,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)



   union select spid,blocked from sysprocesses where  blocked>0







 IF @@ERROR<>0 RETURN @@ERROR 



  



-- 找到临时表的记录数

 select  @intCountProperties = Count(*),@intCounter = 1



 from #tmp_lock_who



 



 IF @@ERROR<>0 RETURN @@ERROR 



 



 if @intCountProperties=0



  select '现在没有阻塞和死锁信息' as message







-- 循环开始

while @intCounter <= @intCountProperties



begin



-- 取第一条记录

  select  @spid = spid,@bl = bl



  from #tmp_lock_who where Id = @intCounter 



 begin



  if @spid =0 



            select '引起数据库死锁的是: '+ CAST(@bl AS VARCHAR(10)) + '进程号,其执行的SQL语法如下'



 else



            select '进程号SPID:'+ CAST(@spid AS VARCHAR(10))+ '' + '进程号SPID:'+ CAST(@bl AS VARCHAR(10)) +'阻塞,其当前进程执行的SQL语法如下'



 DBCC INPUTBUFFER (@bl )



 end 







-- 循环指针下移

 set @intCounter = @intCounter + 1



end







drop table #tmp_lock_who







return 0



end
View Code
 --杀死锁和进程

--如何去手动的杀死进程和锁?最简单的办法,重新启动服务。但是这里要介绍一个存储过程,通过显式的调用,可以杀死进程和锁。

use master



go







if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[p_killspid]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)



drop procedure [dbo].[p_killspid]



GO







create proc p_killspid



@dbname varchar(200)    --要关闭进程的数据库名

as  



    declare @sql  nvarchar(500)  



    declare @spid nvarchar(20)







    declare #tb cursor for



        select spid=cast(spid as varchar(20)) from master..sysprocesses where dbid=db_id(@dbname)



    open #tb



    fetch next from #tb into @spid



    while @@fetch_status=0



    begin  



        exec('kill '+@spid)



        fetch next from #tb into @spid



    end  



    close #tb



    deallocate #tb



go
View Code

 



--用法
exec p_killspid 'newdbpy'

--查看锁信息

--如何查看系统中所有锁的详细信息?在企业管理管理器中,我们可以看到一些进程和锁的信息,这里介绍另外一种方法。

create table #t(req_spid int,obj_name sysname)







declare @s nvarchar(4000)



    ,@rid int,@dbname sysname,@id int,@objname sysname







declare tb cursor for 



    select distinct req_spid,dbname=db_name(rsc_dbid),rsc_objid



    from master..syslockinfo where rsc_type in(4,5)



open tb



fetch next from tb into @rid,@dbname,@id



while @@fetch_status=0



begin



    set @s='select @objname=name from ['+@dbname+']..sysobjects where id=@id'



    exec sp_executesql @s,N'@objname sysname out,@id int',@objname out,@id



    insert into #t values(@rid,@objname)



    fetch next from tb into @rid,@dbname,@id



end



close tb



deallocate tb







select 进程id=a.req_spid



    ,数据库=db_name(rsc_dbid)



    ,类型=case rsc_type when 1 then 'NULL 资源(未使用)'



        when 2 then '数据库'



        when 3 then '文件'



        when 4 then '索引'



        when 5 then ''



        when 6 then ''



        when 7 then ''



        when 8 then '扩展盘区'



        when 9 then 'RID(行 ID)'



        when 10 then '应用程序'



    end



    ,对象id=rsc_objid



    ,对象名=b.obj_name



    ,rsc_indid



 from master..syslockinfo a left join #t b on a.req_spid=b.req_spid







go



drop table #t
View Code

 

 

你可能感兴趣的:(sql)