现在的位置: 首页 > 综合 > 正文

DBA 需要知道N种对数据库性能的监控SQL语句

2018年07月06日 ⁄ 综合 ⁄ 共 7049字 ⁄ 字号 评论关闭
 
--DBA 需要知道N种对数据库性能的监控SQL语句

-- IO问题的SQL内部分析
下面的DMV查询可以来检查当前所有的等待累积值。
Select  wait_type, 
        waiting_tasks_count, 
        wait_time_ms
from     sys.dm_os_wait_stats  
where    wait_type like 'PAGEIOLATCH%'  
order by wait_type

--可以通过运行下面的查询得到每个文件的信息,了解哪个文件经常要做读(num_of_reads/ num_of_bytes_read),
--哪个经常要做写(num_of_writes/ num_of_bytes_written),哪个文件的读写经常要等待(io_stall_read_ms/ io_stall_write_ms/ io_stall)。
select db.name as database_name, f.fileid as file_id,
f.filename as file_name,
i.num_of_reads, i.num_of_bytes_read, i.io_stall_read_ms, 
i.num_of_writes, i.num_of_bytes_written, i.io_stall_write_ms, 
i.io_stall, i.size_on_disk_bytes
from sys.databases db inner join
sys.sysaltfiles f on db.database_id = f.dbid
inner join sys.dm_io_virtual_file_stats(NULL, NULL) i 
on i.database_id = f.dbid and i.file_id = f.fileid

--SQLOS的任务调度算法
--SQL 2005和SQL 2008有个动态管理视图sys.dm_os_schedulers,可以反映当前每个scheduler的状态。
SELECT
    scheduler_id,
    cpu_id,
    parent_node_id,
    current_tasks_count,
    runnable_tasks_count,
    current_workers_count,
    active_workers_count,
    work_queue_count
  FROM sys.dm_os_schedulers;

-- SQL CPU 100%问题
--使用DMV来分析SQL Server启动以来累计使用CPU资源最多的语句。例如下面的语句就可以列出前50名。
select 
    highest_cpu_queries.*,q.dbid, 
    q.objectid, q.number, q.encrypted, q.[text]
from 
    (select top 50 qs.*
    from sys.dm_exec_query_stats qs
    order by qs.total_worker_time desc) as highest_cpu_queries
    cross apply sys.dm_exec_sql_text(plan_handle) as q
order by highest_cpu_queries.total_worker_time desc
go

--我们也可以找到最经常做重编译的存储过程。
select top 25 sql_text.text, sql_handle, plan_generation_num,  execution_count,
    dbid,  objectid 
from sys.dm_exec_query_stats a
    cross apply sys.dm_exec_sql_text(sql_handle) as sql_text
where plan_generation_num >1
order by plan_generation_num desc
go
-- 返回最经常运行的100条语句
SELECT TOP 100
        cp.cacheobjtype
        ,cp.usecounts
        ,cp.size_in_bytes  
        ,qs.statement_start_offset
        ,qs.statement_end_offset
        ,qt.dbid
        ,qt.objectid
        ,SUBSTRING(qt.text,qs.statement_start_offset/2, 
            (case when qs.statement_end_offset = -1 
            then len(convert(nvarchar(max), qt.text)) * 2 
            else qs.statement_end_offset end -qs.statement_start_offset)/2) 
        as statement
FROM sys.dm_exec_query_stats qs
cross apply sys.dm_exec_sql_text(qs.sql_handle) as qt
inner join sys.dm_exec_cached_plans as cp on qs.plan_handle=cp.plan_handle
where cp.plan_handle=qs.plan_handle
and cp.usecounts>4
ORDER BY [dbid],[Usecounts] DESC

-- 返回最经常被修改的100个索引
-- 通过它们的Database_id, object_id, index_id和partition_number
-- 可以找到它们是哪个数据库上的哪个索引
SELECT top 100 * 
FROM sys.dm_db_index_operational_stats(NULL, NULL, NULL, NULL)
order by leaf_insert_count+leaf_delete_count+leaf_update_count desc
GO


-- 返回做IO数目最多的50条语句以及它们的执行计划
select top 50 
    (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_phys_reads,
     Execution_count, 
    statement_start_offset as stmt_start_offset, statement_end_offset as stmt_end_offset,
substring(sql_text.text, (statement_start_offset/2), 
case 
when (statement_end_offset -statement_start_offset)/2 <=0 then 64000
else (statement_end_offset -statement_start_offset)/2
end) as exec_statement,  
sql_text.text,
plan_text.*
from sys.dm_exec_query_stats  
cross apply sys.dm_exec_sql_text(sql_handle) as sql_text
cross apply sys.dm_exec_query_plan(plan_handle) as plan_text
order by 
 (total_logical_reads + total_logical_writes) /Execution_count Desc
go

-- CPU
-- 计算signal wait占整wait时间的百分比
select convert(numeric(5,4),sum(signal_wait_time_ms)/sum(wait_time_ms)) 
from Sys.dm_os_wait_stats

--性能计数对象SQLServer:SQL Statistics下面有几个计数器,可以计算出大致的执行计划重用率。计算方法是:
--Initial Compilations = SQL Compilations/sec – SQL Re-Compilations/sec
--执行计划重用率= (Batch requests/sec – Initial Compilations/sec) / Batch requests/sec


-- 计算'Cxpacket'占整wait时间的百分比
declare @Cxpacket bigint
declare @Sumwaits bigint
select @Cxpacket = wait_time_ms
from Sys.dm_os_wait_stats
where wait_type = 'Cxpacket'
select @Sumwaits = sum(wait_time_ms)
from Sys.dm_os_wait_stats
select convert(numeric(5,4),@Cxpacket/@Sumwaits)

-- 阻塞:
-- 查询当前数据库上所有用户表格在Row lock上发生阻塞的频率
declare @dbid int
select @dbid = db_id()
Select dbid=database_id, objectname=object_name(s.object_id)
, indexname=i.name, i.index_id    --, partition_number
, row_lock_count, row_lock_wait_count
, [block %]=cast (100.0 * row_lock_wait_count / (1 + row_lock_count) as numeric(15,2))
, row_lock_wait_in_ms
, [avg row lock waits in ms]=cast (1.0 * row_lock_wait_in_ms / (1 + row_lock_wait_count) as numeric(15,2))
from sys.dm_db_index_operational_stats (@dbid, NULL, NULL, NULL) s,     sys.indexes i
where objectproperty(s.object_id,'IsUserTable') = 1
and i.object_id = s.object_id
and i.index_id = s.index_id
order by row_lock_wait_count desc

-- 返回当前数据库所有碎片率大于25%的索引
-- 运行本语句会扫描很多数据页面
-- 避免在系统负载比较高时运行
declare @dbid int
select @dbid = db_id()
SELECT * FROM sys.dm_db_index_physical_stats (@dbid, NULL, NULL, NULL, NULL)
where avg_fragmentation_in_percent>25
order by avg_fragmentation_in_percent desc
GO

-- 当前数据库可能缺少的索引
select d.*
        , s.avg_total_user_cost
        , s.avg_user_impact
        , s.last_user_seek
        ,s.unique_compiles
from sys.dm_db_missing_index_group_stats s
        ,sys.dm_db_missing_index_groups g
        ,sys.dm_db_missing_index_details d
where s.group_handle = g.index_group_handle
and d.index_handle = g.index_handle
order by s.avg_user_impact desc
go
---查找未使用过的索引
SELECT TOP 1000
o.name AS 表名
, i.name AS 索引名
, i.index_id AS 索引id
, dm_ius.user_seeks AS 搜索次数
, dm_ius.user_scans AS 扫描次数
, dm_ius.user_lookups AS 查找次数
, dm_ius.user_updates AS 更新次数
, p.TableRows as 表行数
, 'DROP INDEX ' + QUOTENAME(i.name)
+ ' ON ' + QUOTENAME(s.name) + '.' + QUOTENAME(OBJECT_NAME(dm_ius.OBJECT_ID)) AS '删除语句'
FROM sys.dm_db_index_usage_stats dm_ius
INNER JOIN sys.indexes i ON i.index_id = dm_ius.index_id AND dm_ius.OBJECT_ID = i.OBJECT_ID
INNER JOIN sys.objects o ON dm_ius.OBJECT_ID = o.OBJECT_ID
INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
INNER JOIN (SELECT SUM(p.rows) TableRows, p.index_id, p.OBJECT_ID
FROM sys.partitions p GROUP BY p.index_id, p.OBJECT_ID) p
ON p.index_id = dm_ius.index_id AND dm_ius.OBJECT_ID = p.OBJECT_ID
WHERE OBJECTPROPERTY(dm_ius.OBJECT_ID,'IsUserTable') = 1
AND dm_ius.database_id = DB_ID()
AND i.type_desc = 'nonclustered'
AND i.is_primary_key = 0
AND i.is_unique_constraint = 0
and o.name='t_goods'   --根据实际修改表名
ORDER BY (dm_ius.user_seeks + dm_ius.user_scans + dm_ius.user_lookups) ASC

/*
user_updates很大,而发现user_seeks和user_scans很少或者就是0,那就说明该索引一直在更新,
但是从来不被使用,仅仅创建和修改,没有为查询提供任何帮助,就可以考虑删除了
*/
--得到按照执行时间排序的前10 的存储过程的执行信息:

SELECT TOP 10 a.object_id, a.database_id, OBJECT_NAME(object_id, database_id) 'proc name',

a.cached_time, a.last_execution_time, a.total_elapsed_time, a.total_elapsed_time/a.execution_count AS [avg_elapsed_time],

a.execution_count,

a.total_physical_reads/a.execution_count avg_physical_reads,

a.total_logical_writes,

a.total_logical_writes/ a.execution_count  avg_logical_reads,

a.last_elapsed_time,

a.total_elapsed_time / a.execution_count   avg_elapsed_time,

b.text,c.query_plan 

FROM sys.dm_exec_procedure_stats AS a

CROSS APPLY sys.dm_exec_sql_text(a.sql_handle)  b

CROSS APPLY sys.dm_exec_query_plan(a.plan_handle) c

ORDER BY [total_worker_time] DESC;

--100个io读取开销最大的语句
SELECT TOP 100 SUBSTRING(qt.text, (qs.statement_start_offset/2)+1, 
 
  ((CASE qs.statement_end_offset

  WHEN -1 THEN DATALENGTH(qt.text)

  ELSE qs.statement_end_offset

  END - qs.statement_start_offset)/2)+1), 

  qs.execution_count, 

  qs.total_logical_reads, qs.last_logical_reads,

  qs.min_logical_reads, qs.max_logical_reads,

  qs.total_elapsed_time, qs.last_elapsed_time,

  qs.min_elapsed_time, qs.max_elapsed_time,

  qs.last_execution_time,

  qp.query_plan
 
FROM sys.dm_exec_query_stats qs
 
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) qt
 
CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp
 
WHERE qt.encrypted=0
 
ORDER BY qs.total_logical_reads DESC

 

抱歉!评论已关闭.