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


     
    --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
  • 相关阅读:
    字符串匹配——KMP算法(C++)
    数论——Fibonacci数列(C++)
    数据结构——线段树之二(C++)
    数据结构——线段树之一(C++)
    最后的最后
    开始的开始
    10.25模拟 保留道路
    10.25模拟 列车调度
    10.25模拟 三角形
    洛谷 P1093 奖学金
  • 原文地址:https://www.cnblogs.com/davidhou/p/5121673.html
Copyright © 2020-2023  润新知