zoukankan      html  css  js  c++  java
  • MSSQ调优所需用的语句

    看一下各项指标是否正常,是否有阻塞,这个语句选取了前10个最耗CPU时间的会话语句

    SELECT TOP 10
     [session_id],
     [request_id],
     [start_time] AS '开始时间',
     [status] AS '状态',
     [command] AS '命令',
     dest.[text] AS 'sql语句', 
     DB_NAME([database_id]) AS '数据库名',
     [blocking_session_id] AS '正在阻塞其他会话的会话ID',
     [wait_type] AS '等待资源类型',
     [wait_time] AS '等待时间',
     [wait_resource] AS '等待的资源',
     [reads] AS '物理读次数',
     [writes] AS '写次数',
     [logical_reads] AS '逻辑读次数',
     [row_count] AS '返回结果行数'
     FROM sys.[dm_exec_requests] AS der 
     CROSS APPLY 
     sys.[dm_exec_sql_text](der.[sql_handle]) AS dest 
     WHERE [session_id]>50 AND DB_NAME(der.[database_id])='gposdb'  
     ORDER BY [cpu_time] DESC

    如果SQLSERVER存在要等待的资源,那么执行下面语句就会显示出会话中有多少个worker在等待,如果没有则下面语句运行结果为空。

    SELECT TOP 10
     [session_id],
     [request_id],
     [start_time] AS '开始时间',
     [status] AS '状态',
     [command] AS '命令',
     dest.[text] AS 'sql语句', 
     DB_NAME([database_id]) AS '数据库名',
     [blocking_session_id] AS '正在阻塞其他会话的会话ID',
     der.[wait_type] AS '等待资源类型',
     [wait_time] AS '等待时间',
     [wait_resource] AS '等待的资源',
     [dows].[waiting_tasks_count] AS '当前正在进行等待的任务数',
     [reads] AS '物理读次数',
     [writes] AS '写次数',
     [logical_reads] AS '逻辑读次数',
     [row_count] AS '返回结果行数'
     FROM sys.[dm_exec_requests] AS der 
     INNER JOIN [sys].[dm_os_wait_stats] AS dows 
     ON der.[wait_type]=[dows].[wait_type]
     CROSS APPLY 
     sys.[dm_exec_sql_text](der.[sql_handle]) AS dest 
     WHERE [session_id]>50  
     ORDER BY [cpu_time] DESC

    查询CPU占用高的语句

    SELECT TOP 10
        total_worker_time/execution_count AS avg_cpu_cost, plan_handle,
        execution_count,
        (SELECT SUBSTRING(text, statement_start_offset/2 + 1,
           (CASE WHEN statement_end_offset = -1
              THEN LEN(CONVERT(nvarchar(max), text)) * 2
              ELSE statement_end_offset
           END - statement_start_offset)/2)
        FROM sys.dm_exec_sql_text(sql_handle)) AS query_text
     FROM sys.dm_exec_query_stats
    ORDER BY [avg_cpu_cost] DESC

    查询缺失索引

    SELECT 
        DatabaseName = DB_NAME(database_id)
        ,[Number Indexes Missing] = count(*) 
     FROM sys.dm_db_missing_index_details
     GROUP BY DB_NAME(database_id)
     ORDER BY 2 DESC;
     SELECT  TOP 10 
             [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;
    使用DMV来分析SQL Server启动以来累计使用CPU资源最多的语句。例如下面的语句就可以列出前50名
    select 
        c.last_execution_time,c.execution_count,c.total_logical_reads,c.total_logical_writes,c.total_elapsed_time,c.last_elapsed_time, 
        q.[text]
    from 
        (select top 50 qs.*
        from sys.dm_exec_query_stats qs
        order by qs.total_worker_time desc) as c
        cross apply sys.dm_exec_sql_text(plan_handle) as q
    order by c.total_worker_time 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
    返回做IO数目最多的50条语句以及它们的执行计划
    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
    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
    计算signal wait占整wait时间的百分比
    指令等待 CPU 资源的时间占总时间的百分比。如果超过 25% ,说明 CPU 紧张
    select convert(numeric(5,4),sum(signal_wait_time_ms)/sum(wait_time_ms)) 
    from Sys.dm_os_wait_stats 
    
    -- 计算'Cxpacket'占整wait时间的百分比
    -- Cxpacket:Sql Server 在处理一句代价很大的语句,要不就是没有合适的索引或筛选条件没能筛选足够的记录,使得语句要返回大量的结果,当 >5% 说明有问题
    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
    --Begin Index(索引) 分析优化的相关 Sql 
    
    -- 返回当前数据库所有碎片率大于25%的索引
    -- 运行本语句会扫描很多数据页面
    -- 避免在系统负载比较高时运行
    -- 避免在系统负载比较高时运行
    declare @dbid int
    select @dbid = db_id()
    SELECT o.name as tablename,s.* FROM sys.dm_db_index_physical_stats (@dbid, NULL, NULL, NULL, NULL) s,sys.objects o
    where avg_fragmentation_in_percent>25 and o.object_id =s.object_id
    order by avg_fragmentation_in_percent desc
    GO
    
    -- 当前数据库可能缺少的索引
    -- 非常好用的 Sql 语句
    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
    
    -- 自动重建或重新组织索引
    -- 比较好用,慎用,特别是对于在线 DB
    -- Ensure a USE <databasename> statement has been executed first.
    SET NOCOUNT ON;
    DECLARE @objectid int;
    DECLARE @indexid int;
    DECLARE @partitioncount bigint;
    DECLARE @schemaname nvarchar(130); 
    DECLARE @objectname nvarchar(130); 
    DECLARE @indexname nvarchar(130); 
    DECLARE @partitionnum bigint;
    DECLARE @partitions bigint;
    DECLARE @frag float;
    DECLARE @command nvarchar(4000); 
    -- Conditionally select tables and indexes from the sys.dm_db_index_physical_stats function 
    -- and convert object and index IDs to names.
    SELECT
        object_id AS objectid,
        index_id AS indexid,
        partition_number AS partitionnum,
        avg_fragmentation_in_percent AS frag
    INTO #work_to_do
    FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, 'LIMITED')
    WHERE avg_fragmentation_in_percent > 10.0 AND index_id > 0;
    
    -- Declare the cursor for the list of partitions to be processed.
    DECLARE partitions CURSOR FOR SELECT * FROM #work_to_do;
    
    -- Open the cursor.
    OPEN partitions;
    
    -- Loop through the partitions.
    WHILE (1=1)
        BEGIN;
            FETCH NEXT
               FROM partitions
               INTO @objectid, @indexid, @partitionnum, @frag;
            IF @@FETCH_STATUS < 0 BREAK;
            SELECT @objectname = QUOTENAME(o.name), @schemaname = QUOTENAME(s.name)
            FROM sys.objects AS o
            JOIN sys.schemas as s ON s.schema_id = o.schema_id
            WHERE o.object_id = @objectid;
            SELECT @indexname = QUOTENAME(name)
            FROM sys.indexes
            WHERE  object_id = @objectid AND index_id = @indexid;
            SELECT @partitioncount = count (*)
            FROM sys.partitions
            WHERE object_id = @objectid AND index_id = @indexid;
    
    -- 30 is an arbitrary decision point at which to switch between reorganizing and rebuilding.
            IF @frag < 30.0
                SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' REORGANIZE';
            IF @frag >= 30.0
                SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' REBUILD';
            IF @partitioncount > 1
                SET @command = @command + N' PARTITION=' + CAST(@partitionnum AS nvarchar(10));
            EXEC (@command);
            PRINT N'Executed: ' + @command;
        END;
    
    -- Close and deallocate the cursor.
    CLOSE partitions;
    DEALLOCATE partitions;
    
    -- Drop the temporary table.
    DROP TABLE #work_to_do;
    GO
    
    
    -- 查看当前数据库索引的使用率
    -- 非常的有用
    SELECT
    object_name(object_id) as table_name,
    (
    select name
    from sys.indexes
    where object_id = stats.object_id and index_id = stats.index_id
    ) as index_name,
    *
    FROM sys.dm_db_index_usage_stats as stats
    WHERE database_id = DB_ID()
    order by table_name
    
    
    -- 指定表的索引使用情况
    declare @table as nvarchar(100)
    set @table = 't_name';
    
    SELECT
    (
      select name
      from sys.indexes
      where object_id = stats.object_id and index_id = stats.index_id
    ) as index_name,
    *
    FROM sys.dm_db_index_usage_stats as stats
    where object_id = object_id(@table)
    order by user_seeks, user_scans, user_lookups asc
    
    --End Index 分析优化的相关 Sql
     
     
     
     
     
  • 相关阅读:
    物联网数据卡系统源码——物联网的主要应用领域
    一张图看懂开源许可协议,开源许可证GPL、BSD、MIT、Mozilla、Apache和LGPL的区别
    memcached对key和value的限制 memcached的key最大长度和Value最大长度
    缓存技术PK:选择Memcached还是Redis?
    .Net开源框架列表
    项目管理工具Redmine各功能测试
    DBImport V3.7版本发布及软件稳定性(自动退出问题)解决过程分享
    ASP.NET Core 折腾笔记一
    发布:.NET开发人员必备的可视化调试工具(你值的拥有)
    开源发布:VS代码段快捷方式及可视化调试快速部署工具
  • 原文地址:https://www.cnblogs.com/yibinboy/p/4350722.html
Copyright © 2011-2022 走看看