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)

 

 

 

 

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