首页 > 数据库 >sqlserver性能排查脚本

sqlserver性能排查脚本

时间:2024-09-05 10:51:38浏览次数:12  
标签:脚本 text OD sqlserver sys 排查 time query id

 一、CPU问题 1、目前正在发生的cpu问题排查   --累计耗费cpu多统计 PRINT '-- top 10 Active CPU Consuming Queries (aggregated)--'; SELECT TOP 10 GETDATE() runtime, * FROM (SELECT query_stats.query_hash, SUM(query_stats.cpu_time) 'Total_Request_Cpu_Time_Ms', SUM(logical_reads) 'Total_Request_Logical_Reads', MIN(start_time) 'Earliest_Request_start_Time', COUNT(*) 'Number_Of_Requests', SUBSTRING(REPLACE(REPLACE(MIN(query_stats.statement_text), CHAR(10), ' '), CHAR(13), ' '), 1, 256) AS "Statement_Text"     FROM (SELECT req.*, SUBSTRING(ST.text, (req.statement_start_offset / 2)+1, ((CASE statement_end_offset WHEN -1 THEN DATALENGTH(ST.text)ELSE req.statement_end_offset END-req.statement_start_offset)/ 2)+1) AS statement_text             FROM sys.dm_exec_requests AS req                 CROSS APPLY sys.dm_exec_sql_text(req.sql_handle) AS ST ) AS query_stats     GROUP BY query_hash) AS t ORDER BY Total_Request_Cpu_Time_Ms DESC;   ---单次消耗CPU长统计 PRINT '--top 10 Active CPU Consuming Queries by sessions--'; SELECT TOP 10 req.session_id, req.start_time, cpu_time 'cpu_time_ms', OBJECT_NAME(ST.objectid, ST.dbid) 'ObjectName', SUBSTRING(REPLACE(REPLACE(SUBSTRING(ST.text, (req.statement_start_offset / 2)+1, ((CASE statement_end_offset WHEN -1 THEN DATALENGTH(ST.text)ELSE req.statement_end_offset END-req.statement_start_offset)/ 2)+1), CHAR(10), ' '), CHAR(13), ' '), 1, 512) AS statement_text FROM sys.dm_exec_requests AS req     CROSS APPLY sys.dm_exec_sql_text(req.sql_handle) AS ST ORDER BY cpu_time DESC; GO       2、过去发生的CPU高问题分析 -- Top 15 CPU consuming queries by query hash -- Note that a query hash can have many query ids if not parameterized or not parameterized properly WITH AggregatedCPU AS (     SELECT q.query_hash         ,SUM(count_executions * avg_cpu_time / 1000.0) AS total_cpu_ms         ,SUM(count_executions * avg_cpu_time / 1000.0) / SUM(count_executions) AS avg_cpu_ms         ,MAX(rs.max_cpu_time / 1000.00) AS max_cpu_ms         ,MAX(max_logical_io_reads) max_logical_reads         ,COUNT(DISTINCT p.plan_id) AS number_of_distinct_plans         ,COUNT(DISTINCT p.query_id) AS number_of_distinct_query_ids         ,SUM(CASE                 WHEN rs.execution_type_desc = 'Aborted'                     THEN count_executions                 ELSE 0                 END) AS Aborted_Execution_Count         ,SUM(CASE                 WHEN rs.execution_type_desc = 'Regular'                     THEN count_executions                 ELSE 0                 END) AS Regular_Execution_Count         ,SUM(CASE                 WHEN rs.execution_type_desc = 'Exception'                     THEN count_executions                 ELSE 0                 END) AS Exception_Execution_Count         ,SUM(count_executions) AS total_executions         ,MIN(qt.query_sql_text) AS sampled_query_text     FROM sys.query_store_query_text AS qt         INNER JOIN sys.query_store_query AS q ON qt.query_text_id = q.query_text_id         INNER JOIN sys.query_store_plan AS p ON q.query_id = p.query_id         INNER JOIN sys.query_store_runtime_stats AS rs ON rs.plan_id = p.plan_id         INNER JOIN sys.query_store_runtime_stats_interval AS rsi ON rsi.runtime_stats_interval_id = rs.runtime_stats_interval_id     WHERE rs.execution_type_desc IN ('Regular','Aborted','Exception')         AND rsi.start_time >= DATEADD(HOUR, - 2, GETUTCDATE())  ---过去2小时     GROUP BY q.query_hash     )     ,OrderedCPU AS (     SELECT query_hash         ,total_cpu_ms         ,avg_cpu_ms         ,max_cpu_ms         ,max_logical_reads         ,number_of_distinct_plans         ,number_of_distinct_query_ids         ,total_executions         ,Aborted_Execution_Count         ,Regular_Execution_Count         ,Exception_Execution_Count         ,sampled_query_text         ,ROW_NUMBER() OVER (             ORDER BY total_cpu_ms DESC                 ,query_hash ASC             ) AS query_hash_row_number     FROM AggregatedCPU     ) SELECT OD.query_hash     ,OD.total_cpu_ms     ,OD.avg_cpu_ms     ,OD.max_cpu_ms     ,OD.max_logical_reads     ,OD.number_of_distinct_plans     ,OD.number_of_distinct_query_ids     ,OD.total_executions     ,OD.Aborted_Execution_Count     ,OD.Regular_Execution_Count     ,OD.Exception_Execution_Count     ,OD.sampled_query_text     ,OD.query_hash_row_number FROM OrderedCPU AS OD WHERE OD.query_hash_row_number <= 15 --get top 15 rows by total_cpu_ms ---TOP15 ORDER BY total_cpu_ms DESC;   3、CPU统计 --TOP15 CPU查询 SELECT TOP 15 query_stats.query_hash AS Query_Hash,     SUM(query_stats.total_worker_time) / SUM(query_stats.execution_count) AS Avg_CPU_Time,      MIN(query_stats.statement_text) AS Statement_Text FROM     (SELECT QS.*,         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) AS statement_text FROM sys.dm_exec_query_stats AS QS     CROSS APPLY sys.dm_exec_sql_text(QS.sql_handle) AS ST     ) AS query_stats GROUP BY query_stats.query_hash ORDER BY Avg_CPU_Time DESC;   ---TOP 累计CPU耗时查询 SELECT     highest_cpu_queries.plan_handle,     highest_cpu_queries.total_worker_time,     q.dbid,     q.objectid,     q.number,     q.encrypted,     q.[text] FROM     (SELECT TOP 15             qs.plan_handle,             qs.total_worker_time         FROM             sys.dm_exec_query_stats AS 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;     二、IO问题 如果已经出现IO问题, 可以使用 sys.dm_exec_requests 或 sys.dm_os_waiting_tasks 查看 wait_type 和 wait_time。   --统计数据和日志IO量 SELECT     database_name = DB_NAME() ,   UTC_time = end_time ,   'Data IO In % of Limit'                   = rs.avg_data_io_percent ,   'Log Write Utilization In % of Limit'     = rs.avg_log_write_percent FROM sys.dm_db_resource_stats AS rs  --past hour only ORDER BY  rs.end_time DESC;   --统计过去2小时IO活动情况 -- Top queries that waited on buffer -- Note these are finished queries WITH Aggregated AS (SELECT q.query_hash, SUM(total_query_wait_time_ms) total_wait_time_ms, SUM(total_query_wait_time_ms / avg_query_wait_time_ms) AS total_executions, MIN(qt.query_sql_text) AS sampled_query_text, MIN(wait_category_desc) AS wait_category_desc                     FROM sys.query_store_query_text AS qt                          INNER JOIN sys.query_store_query AS q ON qt.query_text_id=q.query_text_id                          INNER JOIN sys.query_store_plan AS p ON q.query_id=p.query_id                          INNER JOIN sys.query_store_wait_stats AS waits ON waits.plan_id=p.plan_id                          INNER JOIN sys.query_store_runtime_stats_interval AS rsi ON rsi.runtime_stats_interval_id=waits.runtime_stats_interval_id                     WHERE wait_category_desc='Buffer IO' AND rsi.start_time>=DATEADD(HOUR, -2, GETUTCDATE())                     GROUP BY q.query_hash), Ordered AS (SELECT query_hash, total_executions, total_wait_time_ms, sampled_query_text, wait_category_desc, ROW_NUMBER() OVER (ORDER BY total_wait_time_ms DESC, query_hash ASC) AS query_hash_row_number                                                         FROM Aggregated) SELECT OD.query_hash, OD.total_executions, OD.total_wait_time_ms, OD.sampled_query_text, OD.wait_category_desc, OD.query_hash_row_number FROM Ordered AS OD WHERE OD.query_hash_row_number <= 15 -- get top 15 rows by total_wait_time_ms ORDER BY total_wait_time_ms DESC; GO   ---查看 WRITELOG 等待类型的日志 I/O 总计 -- Top transaction log consumers -- Adjust the time window by changing -- rsi.start_time >= DATEADD(hour, -2, GETUTCDATE()) WITH AggregatedLogUsed AS (SELECT q.query_hash,            SUM(count_executions * avg_cpu_time / 1000.0) AS total_cpu_ms,            SUM(count_executions * avg_cpu_time / 1000.0) / SUM(count_executions) AS avg_cpu_ms,            SUM(count_executions * avg_log_bytes_used) AS total_log_bytes_used,            MAX(rs.max_cpu_time / 1000.00) AS max_cpu_ms,            MAX(max_logical_io_reads) max_logical_reads,            COUNT(DISTINCT p.plan_id) AS number_of_distinct_plans,            COUNT(DISTINCT p.query_id) AS number_of_distinct_query_ids,            SUM(   CASE                       WHEN rs.execution_type_desc = 'Aborted' THEN                           count_executions                       ELSE 0                   END               ) AS Aborted_Execution_Count,            SUM(   CASE                       WHEN rs.execution_type_desc = 'Regular' THEN                           count_executions                       ELSE 0                   END               ) AS Regular_Execution_Count,            SUM(   CASE                       WHEN rs.execution_type_desc = 'Exception' THEN                           count_executions                       ELSE 0                   END               ) AS Exception_Execution_Count,            SUM(count_executions) AS total_executions,            MIN(qt.query_sql_text) AS sampled_query_text     FROM sys.query_store_query_text AS qt         INNER JOIN sys.query_store_query AS q ON qt.query_text_id = q.query_text_id         INNER JOIN sys.query_store_plan AS p ON q.query_id = p.query_id         INNER JOIN sys.query_store_runtime_stats AS rs ON rs.plan_id = p.plan_id         INNER JOIN sys.query_store_runtime_stats_interval AS rsi ON rsi.runtime_stats_interval_id = rs.runtime_stats_interval_id     WHERE rs.execution_type_desc IN ( 'Regular', 'Aborted', 'Exception' )           AND rsi.start_time >= DATEADD(HOUR, -2, GETUTCDATE())     GROUP BY q.query_hash),      OrderedLogUsed AS (SELECT query_hash,            total_log_bytes_used,            number_of_distinct_plans,            number_of_distinct_query_ids,            total_executions,            Aborted_Execution_Count,            Regular_Execution_Count,            Exception_Execution_Count,            sampled_query_text,            ROW_NUMBER() OVER (ORDER BY total_log_bytes_used DESC, query_hash ASC) AS query_hash_row_number     FROM AggregatedLogUsed) SELECT OD.total_log_bytes_used,        OD.number_of_distinct_plans,        OD.number_of_distinct_query_ids,        OD.total_executions,        OD.Aborted_Execution_Count,        OD.Regular_Execution_Count,        OD.Exception_Execution_Count,        OD.sampled_query_text,        OD.query_hash_row_number FROM OrderedLogUsed AS OD WHERE OD.query_hash_row_number <= 15 -- get top 15 rows by total_log_bytes_used ORDER BY total_log_bytes_used DESC; GO     三、tempdb性能问题 与 tempdb 问题相关的常见等待类型是 PAGELATCH_*(不是 PAGEIOLATCH_*)。 但是,出现 PAGELATCH_* 等待并不总是意味着发生了 tempdb 争用。 这种等待可能还意味着,由于并发请求面向相同的数据页面,发生了用户对象数据页面争用。 若要进一步确认 tempdb 争用,请使用 sys.dm_exec_requests 确认 wait_resource 值是否以 2:x:y 开头,其中 2 tempdb 是数据库 ID,x 是文件 ID,y 是页面 ID。 对于 tempdb 争用,常用的方法是减少或重写依赖于 tempdb 的应用程序代码。 常见的 tempdb 使用区域包括: 临时表 表变量 表值参数 包含使用排序、哈希联接和 spool 的查询计划的查询   ---使用表变量和临时表的TOP统计 SELECT plan_handle, execution_count, query_plan INTO #tmpPlan FROM sys.dm_exec_query_stats      CROSS APPLY sys.dm_exec_query_plan(plan_handle); GO   WITH XMLNAMESPACES('http://schemas.microsoft.com/sqlserver/2004/07/showplan' AS sp) SELECT plan_handle, stmt.stmt_details.value('@Database', 'varchar(max)') AS 'Database' , stmt.stmt_details.value('@Schema', 'varchar(max)') AS 'Schema' , stmt.stmt_details.value('@Table', 'varchar(max)') AS 'table' INTO #tmp2 FROM     (SELECT CAST(query_plan AS XML) sqlplan, plan_handle FROM #tmpPlan) AS p         CROSS APPLY sqlplan.nodes('//sp:Object') AS stmt(stmt_details); GO   SELECT t.plan_handle, [Database], [Schema], [table], execution_count FROM     (SELECT DISTINCT plan_handle, [Database], [Schema], [table]      FROM #tmp2      WHERE [table] LIKE '%@%' OR [table] LIKE '%#%') AS t         INNER JOIN #tmpPlan AS t2 ON t.plan_handle=t2.plan_handle; GO DROP TABLE #tmpPlan DROP TABLE #tmp2     ----长时间运行事务查询 SELECT DB_NAME(dtr.database_id) 'database_name',        sess.session_id,        atr.name AS 'tran_name',        atr.transaction_id,        transaction_type,        transaction_begin_time,        database_transaction_begin_time,        transaction_state,        is_user_transaction,        sess.open_transaction_count,        TRIM(REPLACE(                 REPLACE(                             SUBSTRING(                                         SUBSTRING(                                                     txt.text,                                                     (req.statement_start_offset / 2) + 1,                                                     ((CASE req.statement_end_offset                                                             WHEN -1 THEN                                                                 DATALENGTH(txt.text)                                                             ELSE                                                                 req.statement_end_offset                                                         END - req.statement_start_offset                                                     ) / 2                                                     ) + 1                                                 ),                                         1,                                         1000                                     ),                             CHAR(10),                             ' '                         ),                 CHAR(13),                 ' '             )             ) Running_stmt_text,        recenttxt.text 'MostRecentSQLText' FROM sys.dm_tran_active_transactions AS atr     INNER JOIN sys.dm_tran_database_transactions AS dtr         ON dtr.transaction_id = atr.transaction_id     LEFT JOIN sys.dm_tran_session_transactions AS sess         ON sess.transaction_id = atr.transaction_id     LEFT JOIN sys.dm_exec_requests AS req         ON req.session_id = sess.session_id            AND req.transaction_id = sess.transaction_id     LEFT JOIN sys.dm_exec_connections AS conn         ON sess.session_id = conn.session_id     OUTER APPLY sys.dm_exec_sql_text(req.sql_handle) AS txt     OUTER APPLY sys.dm_exec_sql_text(conn.most_recent_sql_handle) AS recenttxt WHERE atr.transaction_type != 2       AND sess.session_id != @@spid ORDER BY start_time ASC;   四、内存分配问题   ---统计TOP内存消耗语句 SELECT IDENTITY(INT, 1, 1) rowId,     CAST(query_plan AS XML) query_plan,     p.query_id INTO #tmp FROM sys.query_store_plan AS p     INNER JOIN sys.query_store_runtime_stats AS r         ON p.plan_id = r.plan_id     INNER JOIN sys.query_store_runtime_stats_interval AS i         ON r.runtime_stats_interval_id = i.runtime_stats_interval_id WHERE start_time > '2018-10-11 14:00:00.0000000'       AND end_time < '2018-10-17 20:00:00.0000000';   WITH cte AS (SELECT query_id,         query_plan,         m.c.value('@SerialDesiredMemory', 'INT') AS SerialDesiredMemory     FROM #tmp AS t         CROSS APPLY t.query_plan.nodes('//*:MemoryGrantInfo[@SerialDesiredMemory[. > 0]]') AS m(c) ) SELECT TOP 50     cte.query_id,     t.query_sql_text,     cte.query_plan,     CAST(SerialDesiredMemory / 1024. AS DECIMAL(10, 2)) SerialDesiredMemory_MB FROM cte     INNER JOIN sys.query_store_query AS q         ON cte.query_id = q.query_id     INNER JOIN sys.query_store_query_text AS t         ON q.query_text_id = t.query_text_id ORDER BY SerialDesiredMemory DESC;       --统计TOP10内存分配 SELECT TOP 10     CONVERT(VARCHAR(30), GETDATE(), 121) AS runtime,        r.session_id,        r.blocking_session_id,        r.cpu_time,        r.total_elapsed_time,        r.reads,        r.writes,        r.logical_reads,        r.row_count,        wait_time,        wait_type,        r.command,        OBJECT_NAME(txt.objectid, txt.dbid) 'Object_Name',        TRIM(REPLACE(REPLACE(SUBSTRING(SUBSTRING(TEXT, (r.statement_start_offset / 2) + 1,         (  (             CASE r.statement_end_offset                 WHEN - 1                     THEN DATALENGTH(TEXT)                 ELSE r.statement_end_offset                 END - r.statement_start_offset             ) / 2         ) + 1), 1, 1000), CHAR(10), ' '), CHAR(13), ' ')) AS stmt_text,        mg.dop,                                               --Degree of parallelism        mg.request_time,                                      --Date and time when this query requested the memory grant.        mg.grant_time,                                        --NULL means memory has not been granted        mg.requested_memory_kb / 1024.0 requested_memory_mb,  --Total requested amount of memory in megabytes        mg.granted_memory_kb / 1024.0 AS granted_memory_mb,   --Total amount of memory actually granted in megabytes. NULL if not granted        mg.required_memory_kb / 1024.0 AS required_memory_mb, --Minimum memory required to run this query in megabytes.        max_used_memory_kb / 1024.0 AS max_used_memory_mb,        mg.query_cost,                                        --Estimated query cost.        mg.timeout_sec,                                       --Time-out in seconds before this query gives up the memory grant request.        mg.resource_semaphore_id,                             --Non-unique ID of the resource semaphore on which this query is waiting.        mg.wait_time_ms,                                      --Wait time in milliseconds. NULL if the memory is already granted.        CASE mg.is_next_candidate --Is this process the next candidate for a memory grant            WHEN 1 THEN                'Yes'            WHEN 0 THEN                'No'            ELSE                'Memory has been granted'        END AS 'Next Candidate for Memory Grant',        qp.query_plan FROM sys.dm_exec_requests AS r     INNER JOIN sys.dm_exec_query_memory_grants AS mg         ON r.session_id = mg.session_id            AND r.request_id = mg.request_id     CROSS APPLY sys.dm_exec_sql_text(mg.sql_handle) AS txt     CROSS APPLY sys.dm_exec_query_plan(r.plan_handle) AS qp ORDER BY mg.granted_memory_kb DESC;                                                

标签:脚本,text,OD,sqlserver,sys,排查,time,query,id
From: https://www.cnblogs.com/wang-xiaohui/p/18397923

相关文章

  • 基于Springboot的学生信息管理系统的设计与实现(包含源码、sql脚本、导入视频教程)
    ......
  • SQLServer事务复制延迟优化之多并行(多线程)复制
    事务复制的延迟在数据库的主从复制过程中,包括MySQL的主从复制,SQLServer的事务复制等等,鉴于主节点往往是并发写入的,而从节点(SQLServer中叫做订阅节点)在重放主节点的写操作的时候,往往会产生一定时间的延迟,如何降低这种复制延迟,并行复制或者说多线程复制是其中手段之一。 SQLServ......
  • 『功能项目』坐骑UI搭建及脚本控制显/隐【19】
    本章项目成果展示我们打开上一篇18怪物消亡掉落宝箱的项目,本章要做的事情是搭建一个坐骑UI界面,并通过键盘B键/右侧坐骑按钮控制坐骑UI界面的显示与隐藏在背包Bag上创建一个父物体,命名为Middle修改Bag的尺寸将下面资源图片放进Art文件夹将图片放在Art文......
  • shell脚本语言基础(基础理论)
    目录一.初识shell脚本1.1shell的定义1.2shell的分类1.3shell脚本的使用场景 2.shell脚本的详细配置 2.1shell的特性2.2脚本的调用形式2.3读取顺序2.4shell脚本中的快捷键2.5关于通配符2.6shell脚本的编写规范2.7变量的类型一.初识shell脚本1.1shell的定义......
  • 简单写一个扫雷游戏脚本
    (function(){h_lei=function(obj){obj=obj==undefined?{}:obj;var_this=this;_this.dataH=[];_this.dataS=[];_this.big=obj.big==undefined?10:obj.big;......
  • unity ui控件与C#脚本类对应表
    unityui控件与C#脚本类对应表原文中文C#--classesImage图像ImageText-TextMeshPro文本-TextMeshPrcTMP_TextRawImage原始图像RawImagePanel面板ImageToggle切换ToggleSlider滑动条SliderScrollbar滚动条ScrollbarScrollView滚动......
  • Sqlserver openquery
    InsertIntoopenquery()解析:INSERTINTOOPENQUERY([192.168.1.50],'SELECT*FROMNEWDBERP_Test2.jserp.Wo_Modified_Record')VALUES(2,'MO23092200232','220103001077',20,'DXL240509','220103001077',2,&......
  • WebDriver API剖析----执行JavaScript脚本
    页面上的操作有时通过Selenium是无法实现的,如滚动条、时间控件等,此时就需要借助JavaScript来完成。WebDriver提供了一个内置方法来操作JavaScript,代码如下:driver.execute_script(self,script,args)可以通过两种方式在浏览器中执行JavaScript。1、在文档根级别执行JavaScr......
  • 简单可靠的SpringBoot Jar包启动和更新的Shell脚本
    能用脚本执行,就不用手动nohupjava-jar啦。1.参数说明最终代码实现如下,支持四个参数:●operation:start-启动新包/update-更新包●env_para:指定使用哪个配置文件,如test/prod/dev等●new_jar_package_name:新包的名称,这里必须要求脚本的位置在新,旧包的同一目......
  • openresty+redis配合 lua脚本封停 IP
    1.安装openresty-1.21.4.4tar-xzvfopenresty-1.21.4.4.tar.gzcdopenresty-1.21.4.4mkdirmodules#到github中下载ngx_cache_purge-2.3,解压后放到modules里面wgethttp://labs.frickle.com/files/ngx_cache_purge-2.3.tar.gz#编译安装openresty./configure--p......