sql server 常用脚本

1. 查看sql server代理中作业的运行状况的脚本

-- descr : a simple sql script to view sql server jobs run status
-- last_run_status  1:success 0:fail
  select category = jc.name,
  category_id = jc.category_id,
  job_name = j.name,
  job_enabled = j.enabled,
  last_run_time = cast(js.last_run_date as varchar(10)) + '-' + cast(js.last_run_time as varchar(10)),
  last_run_duration = js.last_run_duration,
  last_run_status = js.last_run_outcome,
  last_run_msg = js.last_outcome_message + cast(nullif(js.last_run_outcome,1) as varchar(2)),
  job_created = j.date_created,
  job_modified = j.date_modified
  from msdb.dbo.sysjobs j
  inner join msdb.dbo.sysjobservers js
  on j.job_id = js.job_id
  inner join msdb.dbo.syscategories jc
  on j.category_id = jc.category_id
  where j.enabled = 1
  and js.last_run_outcome in (0,1,3,5) -- 0:Fail 1:Succ 3:Cancel 5:First run
  and jc.category_id not between 10 and 20 -- repl
  --and js.last_run_outcome = 0  只用于查看失败的作业

 

2. 查看always on 同步状态(队列情况)

SELECT  ar.replica_server_name AS [副本名称] ,
       ar.availability_mode_desc as [同步模式],
        DB_NAME(dbr.database_id) AS [数据库名称] ,
        dbr.database_state_desc AS [数据库状态],
        dbr.synchronization_state_desc AS [同步状态],
        dbr.synchronization_health_desc AS [同步健康状态],
        ISNULL(CASE dbr.redo_rate
                 WHEN 0 THEN -1
                 ELSE CAST(dbr.redo_queue_size AS FLOAT) / dbr.redo_rate
               END, -1) AS [Redo延迟(秒)] ,
        ISNULL(CASE dbr.log_send_rate
                 WHEN 0 THEN -1
                 ELSE CAST(dbr.log_send_queue_size AS FLOAT)
                      / dbr.log_send_rate
               END, -1) AS [Log传送延迟(秒)] ,
        dbr.redo_queue_size AS [Redo等待队列(KB)] ,
        dbr.redo_rate AS [Redo速率(KB/S)] ,
        dbr.log_send_queue_size AS [Log传送等待队列(KB)] ,
        dbr.log_send_rate AS [Log传送速率(KB\S)]
FROM    [master].sys.availability_replicas AS AR
        INNER JOIN [master].sys.dm_hadr_database_replica_states AS dbr 
        ON ar.replica_id = dbr.replica_id
WHERE   dbr.redo_queue_size IS NOT NULL
order by DB_NAME(dbr.database_id)

3. 查询当前数据库的脚本(语句)的运行情况(dbcc freeproccache 之后执行次数会再次刷新)

SELECT  creation_time  N'语句编译时间'
        ,last_execution_time  N'上次执行时间'
        ,execution_count  N'执行次数'
        ,case datediff(ss,creation_time,last_execution_time) when 0 then 0 
            else execution_count/datediff(ss,creation_time,last_execution_time) end N'每秒执行次数'
        ,total_physical_reads N'物理读取总次数'
        ,total_logical_reads/execution_count N'每次逻辑读次数'
        ,total_logical_reads  N'逻辑读取总次数'
        ,total_logical_writes N'逻辑写入总次数'
        , total_worker_time/1000 N'所用的CPU总时间ms'
        , total_elapsed_time/1000  N'总花费时间ms'
        , (total_elapsed_time / execution_count)/1000  N'平均时间ms'
        ,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'执行语句'
        ,db_name(st.dbid) as dbname,st.objectid
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st
where last_execution_time >= dateadd(MINUTE,-1,getdate()) and  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   execution_count DESC;

4. 查询当前数据库正在执行的语句

SELECT [Spid] = session_Id ,ecid ,[Database] = DB_NAME(sp.dbid) ,
[User] = nt_username ,[Status] = er.STATUS ,[Wait] = wait_type ,
[Individual Query] = SUBSTRING(qt.TEXT, er.statement_start_offset / 2, ( 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) ,
[Parent Query] = qt.TEXT ,Program = program_name ,Hostname,hostprocess ,loginame ,kpid ,nt_domain ,
start_time
FROM sys.dm_exec_requests er
INNER JOIN sys.sysprocesses sp ON er.session_id = sp.spid
CROSS APPLY sys.dm_exec_sql_text(er.sql_handle) AS qt WHERE session_Id > 50 /* Ignore system spids.*/

5. 查询阻塞情况

SELECT wt.blocking_session_id                  AS BlockingSessesionId
      ,sp.program_name                         AS ProgramName
      ,COALESCE(sp.LOGINAME, sp.nt_username)   AS HostName    
      ,ec1.client_net_address                  AS ClientIpAddress
      ,db.name                                 AS DatabaseName        
      ,wt.wait_type                            AS WaitType                    
      ,ec1.connect_time                        AS BlockingStartTime
      ,wt.WAIT_DURATION_MS/1000                AS WaitDuration
      ,ec1.session_id                          AS BlockedSessionId
      ,h1.TEXT                                 AS BlockedSQLText
      ,h2.TEXT                                 AS BlockingSQLText
FROM sys.dm_tran_locks AS tl
INNER JOIN sys.databases db  ON db.database_id = tl.resource_database_id
INNER JOIN sys.dm_os_waiting_tasks AS wt  ON tl.lock_owner_address = wt.resource_address
INNER JOIN sys.dm_exec_connections ec1  ON ec1.session_id = tl.request_session_id
INNER JOIN sys.dm_exec_connections ec2  ON ec2.session_id = wt.blocking_session_id
LEFT OUTER JOIN master.dbo.sysprocesses sp  ON SP.spid = wt.blocking_session_id
CROSS APPLY sys.dm_exec_sql_text(ec1.most_recent_sql_handle) AS h1
CROSS APPLY sys.dm_exec_sql_text(ec2.most_recent_sql_handle) AS h2
--====================================
--查看正在执行的SQL的阻塞情况
SELECT
R.session_id,
R.command,
R.blocking_session_id,
R.wait_type,
R.wait_resource
FROM sys.dm_exec_requests AS R
WHERE R.session_id>55
AND R.session_id<>@@SPID
复制代码
复制代码
--=================================================================
--查看阻塞链
WITH T1 AS (
        SELECT   S.session_id ,
                ISNULL(RS.blocking_session_id , 0) AS blocking_session_id ,
                CAST('' AS NVARCHAR(200)) AS BlockStep ,
AS BlockNum
        FROM     [sys].[dm_exec_sessions] AS S WITH ( NOLOCK )
        LEFT JOIN [sys].[dm_exec_requests] RS WITH ( NOLOCK )
        ON       S.session_id = RS.session_id
        WHERE    S.session_id IN (
                SELECT  RS1.blocking_session_id
                FROM    [sys].[dm_exec_requests] RS1 )
                AND ISNULL(RS.blocking_session_id , 0) = 0
        UNION ALL
        SELECT   RS.session_id ,
                RS.blocking_session_id ,
                CAST(( '-->'
                        + CAST(RS.blocking_session_id AS NVARCHAR(200))
                        + T1.BlockStep ) AS NVARCHAR(200)) AS BlockStep ,
+ T1.BlockNum AS BlockNum
        FROM     [sys].[dm_exec_requests] RS
        INNER JOIN T1
        ON       RS.blocking_session_id = T1.session_id
        )
SELECT session_id ,
    blocking_session_id ,
    ( CASE WHEN T1.BlockStep = ''
            THEN 'KILL ' + CAST(T1.session_id AS NVARCHAR(200))
            ELSE T1.BlockStep
        END ) AS BlockStep ,
    BlockNum
FROM   T1

6. 查询数据库日志文件的大小

dbcc sqlperf(logspace)
列名 定义

Database Name

数据库名称,为该数据库显示日志统计信息。

Log Size (MB)

分配给日志的当前大小。该大小始终小于最初为日志空间分配的大小,因为 SQL Server 2005 数据库引擎保留了一小部分磁盘空间用于存放内部标头信息。

Log Space Used (%)

事务日志信息当前所占用的日志文件的百分比。

Status

日志文件的状态。始终为 0。

 

 7. 迁移登录用户

select 'create login [' + p.name + '] ' + 
case when p.type in('U','G') then 'from windows ' else '' end + 
'with ' +
case when p.type = 'S' then 'password = ' + master.sys.fn_varbintohexstr(l.password_hash) + 
' hashed, ' + 'sid = ' + master.sys.fn_varbintohexstr(l.sid) + ', check_expiration = ' +
case when l.is_expiration_checked > 0 then 'ON, ' else 'OFF, ' end + 'check_policy = ' + 
case when l.is_policy_checked > 0 then 'ON, ' else 'OFF, ' end +
case when l.credential_id > 0 then 'credential = ' + c.name + ', ' else '' end 
else '' end +
'default_database = ' + p.default_database_name +
case when len(p.default_language_name) > 0 
then ', default_language = "' + p.default_language_name +'"' else '''' end
from sys.server_principals p
    left join sys.sql_logins l on p.principal_id = l.principal_id
    left join sys.credentials c on l.credential_id = c.credential_id
where p.type in('S','U','G') and p.name <> 'sa'

8. 检查文件空间的方法:
使用 exec sp_spaceused 查看的时候,结果比较笼统,不过也是可行的;
建议同时运行下面两条命令:

use<数据库>
go
dbcc showfilestats 
go
dbcc sqlperf(logspace)
go

其中“dbcc showfilestats”命令会以Extent为单位,统计当前数据库下所有数据文件里有多少个Extent,其中有多少个被使用过了,一个Extent是64K,乘一下即可得到数据文件大小,该命令直接从系统分配页面上面读取区分配信息,能够快速准确地计算出一个数据库数据文件区的总数和已使用过的区的数目,而系统分配页上的信息永远是实时更 新的,所以这种统计方法比较准确可靠。在服务器负载很高的情况下也能安全执行,不会增加额外系统负担;

“dbcc sqlperf(logspace)”命令的输出非常浅显易懂。它返回SQL里所有数据库的日志文件当前使用量,该命令的输出也非常快速准确,使用安全。

运行以下查询,可以得到具体库中表的具体空间使用信息:

use xxxxDB   --需要查询的库名
SELECT o.name as name , 
SUM (p.reserved_page_count) as reserved_page_count, 
SUM (p.used_page_count) as used_page_count ,
SUM ( CASE WHEN (p.index_id <2) THEN (p.in_row_data_page_count + p.lob_used_page_count + p.row_overflow_used_page_count) ELSE p.lob_used_page_count + p.row_overflow_used_page_count END ) as DataPages,
SUM ( CASE WHEN (p.index_id <2) THEN row_count ELSE 0 END ) as rowCounts
FROM sys.dm_db_partition_stats as p  join sys.objects as o 
on p.object_id = o.object_id
group by o.name 
order by reserved_page_count desc

输出结果

第一列name是每个表的名字。

SQL Server在使用数据页的时候,为了提高速度,会先把一些页面一次预留”reserve”给表格,然后真正有数据插入的时候,再使用。所以这里有两 列,Reserved_page_count和Used_page_count。两列的结果相差一般不会很多。所以粗略来 讲,Reserved_page_count*8K,就是这张表格占用的空间大小。

DataPages是这张表数据本身占有的空间。因此,(Used_page_count – DataPages)就是索引所占有的空间。索引的个数越多,需要的空间也会越多。
RowCounts,是现在这个表里有多少行数据。

9. 查看sqlserver中表、存储过程、视图等创建以及修改时间:
  a)、直接通过对象资源管理详细信息查看(选中相关项,按F7即可)。
  b)、直接通过sql语句查看

--查看表的结构
select column_name,data_type from information_schema.columns where table_name = '表名'
--查看用户表的创建时间以及修改时间
 select name,create_date ,modify_date from sys.all_objects where type_desc  in ('USER_TABLE')

--查看存储过程的创建时间以及修改时间
 select name,create_date ,modify_date from sys.all_objects where type_desc  in ('SQL_STORED_PROCEDURE')
 --查看视图的创建时间以及修改时间
 select name,create_date ,modify_date from sys.all_objects where type_desc  in ('VIEW')

10. 查看数据库具体表上的索引的使用情况

use xxx --改成要查看的数据库

select db_name(database_id) as N'数据库名称',
       object_name(a.object_id) as N'表名',
       b.name N'索引名称',
       user_seeks N'用户索引查找次数',
       user_scans N'用户索引扫描次数',
       last_user_seek N'最后查找时间',
       last_user_scan N'最后扫描时间',
       rows as N'表中的行数'
from sys.dm_db_index_usage_stats a join 
     sys.indexes b
     on a.index_id = b.index_id
     and a.object_id = b.object_id
     join sysindexes c
     on c.id = b.object_id
where database_id=db_id('xxx')   ---改成要查看的数据库
and object_name(a.object_id) not like 'sys%'
and object_name(a.object_id) = 'xxx'   --改成要查看的表名,此步可省略(即查看某库所有索引)
order by user_scans desc

11. 查看某个表的具体的增长情况

--每十分钟统计某表的数据变动情况(副本库查询)
--通过该char(15)可改变统计时间间隔,时间列如 2016-05-17 15:09:53.627
use xxxxDB
select convert(char(15),时间列,120),count(1)
from 表名 with (nolock)
where 自增列 > (select max(自增列)-条目数 from 表名 )
group by convert(char(15),时间列,120)

12. 查询指定数据的每月的备份文件增长情况

select AVG(backup_size)/1024/1024 as "backup_size MB" ,convert(char(7),backup_finish_date,120) as backup_date
FROM msdb.dbo.backupset
WHERE
[database_name] = N'xxxxxDB'
and server_name = 'yyyyy'
group by convert(char(7),backup_finish_date,120)
order by convert(char(7),backup_finish_date,120)
-- 按月统计指定数据库的增长
-- xxxxxDB  数据库
-- yyyyy  数据库所在服务器的主机名

13. 查询得到1-100的连续数字(区间可改)

select number from master..spt_values where type = 'p'  and number between 1 and 100

14. 查询具体表的行数

SELECT rows FROM sysindexes WHERE id =OBJECT_ID('table_name') AND indid <2

15. 查看数据库服务器上所有的IO负载的排名(IO负载分布状况)

-- Get I/O utilization by database (Query 31) (IO Usage By Database)
WITH Aggregate_IO_Statistics
AS
(SELECT DB_NAME(database_id) AS [Database Name],
CAST(SUM(num_of_bytes_read + num_of_bytes_written)/1048576 AS DECIMAL(12, 2)) AS io_in_mb
FROM sys.dm_io_virtual_file_stats(NULL, NULL) AS [DM_IO_STATS]
GROUP BY database_id)
SELECT ROW_NUMBER() OVER(ORDER BY io_in_mb DESC) AS [I/O Rank], [Database Name], io_in_mb AS [Total I/O (MB)],
       CAST(io_in_mb/ SUM(io_in_mb) OVER() * 100.0 AS DECIMAL(5,2)) AS [I/O Percent]
FROM Aggregate_IO_Statistics
ORDER BY [I/O Rank] OPTION (RECOMPILE);
-- Helps determine which database is using the most I/O resources on the instance

16. 明确的数据库服务器上所有数据库的高读和写延迟(数据库文件的IO延迟)

--下面的查询返回哪个数据库文件有最大的I/O延迟:
-- Calculates average stalls per read, per write,
-- and per total input/output for each database file.
SELECT DB_NAME(fs.database_id) AS [Database Name], mf.physical_name,
io_stall_read_ms, num_of_reads,
CAST(io_stall_read_ms/(1.0 + num_of_reads) AS NUMERIC(10,1)) AS
[avg_read_stall_ms],io_stall_write_ms,
num_of_writes,CAST(io_stall_write_ms/(1.0+num_of_writes) AS NUMERIC(10,1)) AS
[avg_write_stall_ms],
io_stall_read_ms + io_stall_write_ms AS [io_stalls], num_of_reads + num_of_writes
AS [total_io],
CAST((io_stall_read_ms + io_stall_write_ms)/(1.0 + num_of_reads + num_of_writes) AS
NUMERIC(10,1))
AS [avg_io_stall_ms]
FROM sys.dm_io_virtual_file_stats(null,null) AS fs
INNER JOIN sys.master_files AS mf WITH (NOLOCK)
ON fs.database_id = mf.database_id
AND fs.[file_id] = mf.[file_id]
ORDER BY avg_io_stall_ms DESC OPTION (RECOMPILE);
-- Helps determine which database files on
-- the entire instance have the most I/O bottlenecks

17. 查询指定数据库中总物理读最高的查询以及相关信息(排名前十的)

SELECT TOP 10
        t.text ,
        execution_count ,
        statement_start_offset AS stmt_start_offset ,
        sql_handle ,
        plan_handle ,
        total_logical_reads / execution_count AS avg_logical_reads ,
        total_logical_writes / execution_count AS avg_logical_writes ,
        total_physical_reads / execution_count AS avg_physical_reads,t.dbid
FROM    sys.dm_exec_query_stats AS s
        CROSS APPLY sys.dm_exec_sql_text(s.sql_handle) AS t
--WHERE    DB_NAME(t.dbid) = 'AdventureWorks2008R2'
ORDER BY avg_physical_reads DESC;

18. 将所有数据库的恢复模式设置成简单模式(系统数据库除外)

USE [master]
GO
--alter database model set recovery simple with no_wait
declare
        @sqltext varchar(1000),
        @dbname varchar(500)
declare  mycursor cursor for
select name from sys.databases where database_id >4
open mycursor
fetch next from mycursor into @dbname
while @@FETCH_STATUS=0
begin 
print @dbname
set @sqltext='ALTER DATABASE ['+@dbname+'] SET RECOVERY SIMPLE WITH NO_WAIT'
exec (@sqltext)
--print @sqltext

fetch next from mycursor into @dbname
end

close mycursor
deallocate mycursor

19. 查看文件组信息

--查看具体指定数据库的文件组信息
use xxxDB
SELECT df.[name], df.physical_name, df.[size], df.growth, fg.[name]
[filegroup], fg.is_default
FROM sys.database_files df
JOIN sys.filegroups fg
ON df.data_space_id = fg.data_space_id

20. 判断表是堆表还是聚集索引表

--通过判断index_id的值,区分表的类型
--当index_id为0时,则为堆表
--当index_id为1时,则为聚集索引表

select object_name(a.object_id),
case a.index_id when 0 then '堆表'
                when 1 then '聚集索引表'
                end table_type
from sys.partitions a
where a.index_id<2
group by a.object_id,a.index_id

21. 如何正确判断何时使用堆表和聚集索引表

我们有很多理由去创建一个聚集索引表,而非堆表。那么最大的理由可能就是:当一个非聚集索引包含的列不能完全符合一条查询(select)时,执行计划可通过聚集索引查找,而非通过表扫描的方式。

那么我们为什么会选择堆表,原因大致就如下2点: 
1. 堆表没有聚集索引,因此堆表可节省索引的磁盘空间 
2. 堆表没有聚集索引,且数据组织是无序的,节省了排序操作,写入操作更快。

特别注意:在聚集索引索引表上创建分区时,务必检查sql脚本。若设置的分区函数指定的列不是聚集索引列,将会导致聚集索引的变化(删除与重建),最终导致表的类型转换

22. 查看当前实例运行的事务(事务的回话id,运行时长,事务类型等等)

SELECT ST.session_id AS spid,
ST.transaction_id AS TransactionID ,
DB_NAME(DT.database_id) AS DatabaseName ,
AT.transaction_begin_time AS TransactionStartTime ,
DATEDIFF(SECOND, AT.transaction_begin_time, GETDATE()) AS TransactionDuration ,
CASE AT.transaction_type
WHEN 1 THEN 'Read/Write Transaction'
WHEN 2 THEN 'Read-Only Transaction'
WHEN 3 THEN 'System Transaction'
WHEN 4 THEN 'Distributed Transaction'
END AS TransactionType ,
CASE AT.transaction_state
WHEN 0 THEN 'Transaction Not Initialized'
WHEN 1 THEN 'Transaction Initialized & Not Started'
WHEN 2 THEN 'Active Transaction'
WHEN 3 THEN 'Transaction Ended'
WHEN 4 THEN 'Distributed Transaction Initiated Commit Process'
WHEN 5 THEN 'Transaction in Prepared State & Waiting Resolution'
WHEN 6 THEN 'Transaction Committed'
WHEN 7 THEN 'Transaction Rolling Back'
WHEN 8 THEN 'Transaction Rolled Back'
END AS TransactionState
FROM sys.dm_tran_session_transactions AS ST
INNER JOIN sys.dm_tran_active_transactions AS AT ON ST.transaction_id = AT.transaction_id
INNER JOIN sys.dm_tran_database_transactions AS DT ON ST.transaction_id = DT.transaction_id
where ST.is_user_transaction=1 ORDER BY TransactionStartTime
go

23. 批量删除事务(或者联系22中事务查看方法进行删除)

declare @sessionid int
,@sqltxt varchar(max)
declare mycursor cursor for
select session_id
from sys.dm_tran_session_transactions 
where is_user_transaction=1 

open mycursor
fetch next from mycursor into @sessionid
while @@FETCH_STATUS = 0

begin 

--print @sessionid
set @sqltxt = 'kill '+convert(varchar(5),@sessionid)
print @sqltxt
exec (@sqltxt)
fetch next from mycursor into @sessionid
end 
close mycursor
deallocate mycursor

24. 查看sqlserver日志具体报错信息(根据错误编号以及严重性等级)

select * from  sys.messages where message_id = 17836 and language_id = 2052
---在网络数据包负载中指定的长度与读取的字节数不匹配;该连接已关闭。请与客户端库的供应商联系。%1!

25. 查看sqlserver指定表的索引信息

SELECT
索引名称=a.name
,表名=c.name
,索引字段名=d.name
,索引字段位置=d.colid
,c.status
FROM sysindexes a
JOIN sysindexkeys b ON a.id=b.id AND a.indid=b.indid
JOIN sysobjects c ON b.id=c.id
JOIN syscolumns d ON b.id=d.id AND b.colid=d.colid
WHERE a.indid NOT IN(0,255)
and c.xtype='U' --and c.status>0 --查所有用户表
AND c.name='GamePay' --查指定表
ORDER BY c.name,a.name,d.name;

26. 查看sqlserver实例上的锁以及解除锁

查看被锁表:

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)

27. 关闭指定数据库的连接(正在执行的sql)

USE master
go
DECLARE @Sql NVARCHAR(max)
SET @Sql=''
select @Sql=@Sql+'kill '+cast(spid as varchar(50))+';' from sys.sysprocesses where dbid=DB_ID('数据库名')
EXEC(@Sql)

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章