SqlServer占用CPU过高情况排查

一、问题描述

反馈SQLServer中出现CPU使用率过高有许多可能原因,但常见的原因如下最为常见:

  • 由于以下情况,表或索引扫描导致的高逻辑读取:
    • 过期统计信息
    • 缺少索引
    • 设计不佳的查询
  • 工作负载增加

针对此类问题,微软有一套的排查套路,整理记录在此。

近阶段程序运行过程中,发现CPU占用特别高,导致程序运行速度很慢,当时监测的CPU运行情况如下,该版本的SqlServer数据库最多可以使用40个CPU逻辑处理单元,全部100%

二、处理步骤

步骤1,验证 SQL Server 是否导致 CPU 使用率过高


使用以下工具之一检查 SQL Server 进程是否确实导致 CPU 使用率过高:任务管理器:在“进程”选项卡上,检查“64 位版本的 SQL Server Windows NT”的“CPU”列的值是否接近 100%。
性能和资源监视器
计数器:Process/%User Time, % Privileged Time
实例:sqlservr
可以使用以下 PowerShell 脚本在 60 秒的跨度内收集计数器数据:


   
   
  1. $serverName = $env:COMPUTERNAME
  2. $Counters = @(
  3. ( "\\$serverName" + "\Process(sqlservr*)\% User Time"), ( "\\$serverName" + "\Process(sqlservr*)\% Privileged Time")
  4. )
  5. Get-Counter -Counter $Counters -MaxSamples 30 | ForEach {
  6. $_.CounterSamples | ForEach {
  7. [pscustomobject]@{
  8. TimeStamp = $_.TimeStamp
  9. Path = $_.Path
  10. Value = ([Math] ::Round($_.CookedValue, 3))
  11. }
  12. Start-Sleep -s 2
  13. }
  14. }

如果 % User Time 始终大于 90%,则是 SQL Server 进程导致 CPU 使用率过高。 但是,如果 % Privileged time 始终大于 90%,则是防病毒软件、其他驱动程序或计算机上的其他操作系统组件导致 CPU 使用率过高。

步骤2,确定影响 CPU 使用率的查询


如果 Sqlservr.exe 进程导致 CPU 使用率过高,则最常见的原因是执行表或索引扫描的 SQL Server 查询,其次是排序、哈希操作和循环 (嵌套循环运算符或 WHILE (T-SQL) ) 。 要了解查询当前在总 CPU 使用率中的占比,请运行以下语句:


   
   
  1. DECLARE @init_ sum_cpu_ time int,
  2. @utilizedCpuCount int
  3. -- get CPU count used by SQL Server
  4. SELECT @utilizedCpuCount = COUNT( * )
  5. FROM sys.dm_os_schedulers
  6. WHERE status = 'VISIBLE ONLINE'
  7. --calculate the CPU usage by queries OVER a 5 sec interval
  8. SELECT @init_ sum_cpu_ time = SUM(cpu_ time)
  9. FROM sys.dm_exec_requests WAITFOR DELAY '00:00:05' SELECT CONVERT(DECIMAL( 5,
  10. 2),
  11. (( SUM(cpu_ time) - @init_ sum_cpu_ time) / (@utilizedCpuCount * 5000.00)) * 100) AS [CPU FROM Queries AS Percent of Total CPU Capacity]
  12. FROM sys.dm_exec_requests

若要确定当前负责高 CPU 活动的查询,请运行以下语句:


    
    
  1. SELECT TOP 10 s.session_id,
  2. r. status,
  3. r.cpu_ time,
  4. r.logical_reads,
  5. r.reads,
  6. r.writes,
  7. r.total_elapsed_ time / ( 1000 * 60) 'Elaps M',
  8. SUBSTRING(st.TEXT, (r.statement_ start_offset / 2) + 1,
  9. ((CASE r.statement_ end_offset
  10. WHEN - 1 THEN DATALENGTH(st.TEXT)
  11. ELSE r.statement_ end_offset
  12. END - r.statement_ start_offset) / 2) + 1) AS statement_text,
  13. COALESCE(QUOTENAME(DB_NAME(st.dbid)) + N '.' + QUOTENAME( OBJECT_SCHEMA_NAME(st.objectid, st.dbid))
  14. + N '.' + QUOTENAME( OBJECT_NAME(st.objectid, st.dbid)), '') AS command_text,
  15. r.command,
  16. s.login_name,
  17. s.host_name,
  18. s. program_name,
  19. s. last_request_ end_ time,
  20. s.login_ time,
  21. r. open_transaction_ count
  22. FROM sys.dm_exec_sessions AS s
  23. JOIN sys.dm_exec_requests AS r ON r.session_id = s.session_id CROSS APPLY sys.Dm_exec_sql_text(r.sql_handle) AS st
  24. WHERE r.session_id ! = @@SPID
  25. ORDER BY r.cpu_ time DESC

如果查询目前未驱动 CPU,可以运行以下语句来查找历史占用大量 CPU 的查询:


    
    
  1. SELECT TOP 10 st.text AS batch_text,
  2. SUBSTRING(st.TEXT, (qs.statement_ start_offset / 2) + 1, ((CASE qs.statement_ end_offset WHEN - 1 THEN DATALENGTH(st.TEXT) ELSE qs.statement_ end_offset END - qs.statement_ start_offset) / 2) + 1) AS statement_text,
  3. (qs.total_worker_ time / 1000) / qs.execution_ count AS avg_cpu_ time_ms,
  4. (qs.total_elapsed_ time / 1000) / qs.execution_ count AS avg_elapsed_ time_ms,
  5. qs.total_logical_reads / qs.execution_ count AS avg_logical_reads,
  6. (qs.total_worker_ time / 1000) AS cumulative_cpu_ time_ all_executions_ms,
  7. (qs.total_elapsed_ time / 1000) AS cumulative_elapsed_ time_ all_executions_ms
  8. FROM sys.dm_exec_query_stats qs
  9. CROSS APPLY sys.dm_exec_sql_text(sql_handle) st
  10. ORDER BY(qs.total_worker_ time / qs.execution_ count) DESC

步骤 3:更新统计信息

在确定 CPU 占用最高的查询后,请更新这些查询使用的表的“更新统计信息” 。 可以使用 sp_updatestats 系统存储过程更新当前数据库中所有用户定义表和内部表的统计信息。

exec sp_updatestats

   
   

sp_updatestats系统存储过程针对当前数据库中的所有用户定义表和内部表运行UPDATE STATISTICS。

步骤 4:添加缺失索引

缺少索引可能导致运行速度较慢的查询和 CPU 使用率过高。 可以识别缺失的索引并创建这些索引,以改善这种性能影响。


   
   
  1. -- Captures the Total CPU time spent by a query along with the query plan and total executions
  2. SELECT
  3. qs_cpu.total_worker_ time / 1000 AS total_cpu_ time_ms,
  4. q.[text],
  5. p.query_plan,
  6. qs_cpu.execution_ count,
  7. q.dbid,
  8. q.objectid,
  9. q.encrypted AS text_encrypted
  10. FROM
  11. ( SELECT TOP 500 qs.plan_handle,
  12. qs.total_worker_ time,
  13. qs.execution_ count FROM sys.dm_exec_query_stats qs ORDER BY qs.total_worker_ time DESC) AS qs_cpu
  14. CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS q
  15. CROSS APPLY sys.dm_exec_query_plan(plan_handle) p
  16. WHERE p.query_plan.exist( 'declare namespace
  17. qplan = "http://schemas.microsoft.com/sqlserver/2004/07/showplan";
  18. //qplan:MissingIndexes') = 1

2、查看已标识查询的执行计划,并通过进行所需的更改来优化查询。 以下屏幕截图显示了一个示例,其中 SQL Server 将指出查询的缺失索引。 右键单击查询计划的“缺失索引”部分,然后选择“缺少索引详细信息”,在 SQL Server Management Studio 的另一个窗口中创建索引。

3. 使用以下查询检查是否缺少索引,并应用具有高改进度量值的任何建议索引。 从输出中具有最高 improvement_measure 值的前 5 或 10 条建议开始。 这些索引对性能有最显著的积极影响。 确定是否要应用这些索引,并确保对应用程序进行了性能测试。 然后,继续应用缺失索引建议,直到获得所需的应用程序性能结果。


   
   
  1. SELECT CONVERT(VARCHAR( 30), GETDATE(), 126) AS runtime,
  2. mig. index_ group_handle,
  3. mid. index_handle,
  4. CONVERT(DECIMAL( 28, 1), migs.avg_total_user_cost * migs.avg_user_impact * (migs.user_seeks + migs.user_scans)) AS improvement_measure,
  5. 'CREATE INDEX missing_index_' + CONVERT(VARCHAR, mig. index_ group_handle) + '_' + CONVERT(VARCHAR, mid. index_handle) + ' ON ' + mid.statement + ' (' + ISNULL(mid.equality_ columns,
  6. '') + CASE WHEN mid.equality_ columns IS NOT NULL
  7. AND mid.inequality_ columns IS NOT NULL THEN ','
  8. ELSE ''
  9. END + ISNULL(mid.inequality_ columns,
  10. '') + ')' + ISNULL( ' INCLUDE (' + mid.included_ columns + ')',
  11. '') AS create_ index_statement,
  12. migs. *,
  13. mid.database_id,
  14. mid.[ object_id]
  15. FROM sys.dm_db_missing_ index_groups mig
  16. INNER JOIN sys.dm_db_missing_ index_ group_stats migs ON migs. group_handle = mig. index_ group_handle
  17. INNER JOIN sys.dm_db_missing_ index_details mid ON mig. index_handle = mid. index_handle
  18. WHERE CONVERT (DECIMAL ( 28, 1),
  19. migs.avg_total_user_cost * migs.avg_user_impact * (migs.user_seeks + migs.user_scans)) > 10
  20. ORDER BY migs.avg_total_user_cost * migs.avg_user_impact * (migs.user_seeks + migs.user_scans) DESC

 

步骤 5:调查并解决参数敏感问题

可以使用 DBCC FREEPROCCACHE 命令释放计划缓存,并检查这是否解决了 CPU 使用率过高的问题。 如果问题已修复,则表示是参数敏感问题(PSP,也称为“参数探查问题”)。

使用不带参数的 DBCC FREEPROCCACHE 将从计划缓存中删除所有已编译的计划。 这将导致再次编译新的查询执行,从而导致每个新查询的持续时间一次性延长。 最佳方法是使用 DBCC FREEPROCCACHE ( plan_handle | sql_handle ) 来识别导致问题的查询,然后解决单个查询或有问题的查询。

将 DBCC FREEPROCCACHE 命令用作临时解决方案,直到应用程序代码修复为止。 可以使用 DBCC FREEPROCCACHE (plan_handle) 命令仅删除导致问题的计划。 例如,若要查找引用 AdventureWorks 中 Person.Person 表的查询计划,可以使用此查询查找查询句柄。 然后,可以使用查询结果第二列中生成的 DBCC FREEPROCCACHE (plan_handle),从缓存中释放特定查询计划。


   
   
  1. SELECT text, 'DBCC FREEPROCCACHE (0x' + CONVERT( VARCHAR ( 512), plan_handle, 2) + ')' AS dbcc_freeproc_command FROM sys.dm_exec_cached_plans
  2. CROSS APPLY sys.dm_exec_query_plan(plan_handle)
  3. CROSS APPLY sys.dm_exec_sql_text(plan_handle)
  4. WHERE text LIKE '%person.person%'

步骤 6:调查并解决 SARGability 问题

当 SQL Server 引擎可以使用索引查找来加快查询的执行速度时,查询中的谓词将被视为 SARGable (Search ARGument-able)。 许多查询设计会阻止 SARGability,并导致表或索引扫描和 CPU 使用率过高。 请考虑 AdventureWorks 数据库的以下查询,其中必须检索每个 ProductNumber 并向其应用 SUBSTRING() 函数,然后再将其与字符串文本值进行比较。 如你所见,必须先提取表的所有行,然后应用函数,然后才能进行比较。 从表中提取所有行意味着表或索引扫描,这会导致 CPU 使用率较高。


   
   
  1. # 函数查询方法
  2. SELECT ProductID, Name, ProductNumber
  3. FROM [Production].[Product]
  4. WHERE SUBSTRING(ProductNumber, 0, 4) = 'HN-'
  5. # 谓词模糊方法
  6. SELECT ProductID, Name, ProductNumber
  7. FROM [Production].[Product]
  8. WHERE Name LIKE 'Hex%'
  9. # 谓词计算方法
  10. SELECT DISTINCT SalesOrderID, UnitPrice, UnitPrice * 0.10 [ 10% Commission]
  11. FROM [Sales].[SalesOrderDetail]
  12. WHERE UnitPrice * 0.10 > 300

步骤 7:禁用重度跟踪

检查 SQL 跟踪或 XEvent 跟踪,这些跟踪会影响 SQL Server 性能并导致 CPU 使用率过高。 例如,如果跟踪重度 SQL Server 活动,使用以下事件可能会导致 CPU 使用率过高:

  • 查询计划 XML 事件 (query_plan_profile, query_post_compilation_showplan, query_post_execution_plan_profile,
  • query_post_execution_showplan, query_pre_execution_showplan)
  • 语句级事件 (sql_statement_completed, sql_statement_starting, sp_statement_starting, sp_statement_completed)
  • 登录和注销事件 (login, process_login_finish, login_event, logout)
  • 锁定事件 (lock_acquired, lock_cancel, lock_released)
  • 等待事件 (wait_info, wait_info_external)
  • SQL 审核事件(取决于该组中审核的组和 SQL Server 活动)

运行以下查询以确定活动的 XEvent 或 Server 跟踪:


   
   
  1. PRINT '--Profiler trace summary--'
  2. SELECT traceid, property, CONVERT(VARCHAR( 1024), value) AS value FROM ::fn_trace_getinfo(
  3. default)
  4. GO
  5. PRINT '--Trace event details--'
  6. SELECT trace_id,
  7. status,
  8. CASE WHEN row_ number = 1 THEN path ELSE NULL end AS path,
  9. CASE WHEN row_ number = 1 THEN max_ size ELSE NULL end AS max_ size,
  10. CASE WHEN row_ number = 1 THEN start_ time ELSE NULL end AS start_ time,
  11. CASE WHEN row_ number = 1 THEN stop_ time ELSE NULL end AS stop_ time,
  12. max_files,
  13. is_rowset,
  14. is_rollover,
  15. is_shutdown,
  16. is_ default,
  17. buffer_ count,
  18. buffer_ size,
  19. last_event_ time,
  20. event_ count,
  21. trace_event_id,
  22. trace_event_name,
  23. trace_ column_id,
  24. trace_ column_name,
  25. expensive_event
  26. FROM
  27. ( SELECT t.id AS trace_id,
  28. row_ number() over(PARTITION BY t.id order by te.trace_event_id, tc.trace_ column_id) AS row_ number,
  29. t. status,
  30. t.path,
  31. t.max_ size,
  32. t. start_ time,
  33. t. stop_ time,
  34. t.max_files,
  35. t. is_rowset,
  36. t. is_rollover,
  37. t. is_shutdown,
  38. t. is_ default,
  39. t.buffer_ count,
  40. t.buffer_ size,
  41. t. last_event_ time,
  42. t.event_ count,
  43. te.trace_event_id,
  44. te.name AS trace_event_name,
  45. tc.trace_ column_id,
  46. tc.name AS trace_ column_name,
  47. CASE WHEN te.trace_event_id in ( 23, 24, 40, 41, 44, 45, 51, 52, 54, 68, 96, 97, 98, 113, 114, 122, 146, 180) THEN CAST( 1 as bit) ELSE CAST( 0 AS BIT) END AS expensive_event FROM sys.traces t CROSS APPLY ::fn_trace_geteventinfo(t.id) AS e JOIN sys.trace_events te ON te.trace_event_id = e.eventid JOIN sys.trace_ columns tc ON e.columnid = trace_ column_id) AS x
  48. GO
  49. PRINT '--XEvent Session Details--'
  50. SELECT sess.NAME 'session_name', event_name, xe_event_name, trace_event_id,
  51. CASE WHEN xemap.trace_event_id IN( 23, 24, 40, 41, 44, 45, 51, 52, 54, 68, 96, 97, 98, 113, 114, 122, 146, 180)
  52. THEN Cast( 1 AS BIT)
  53. ELSE Cast( 0 AS BIT)
  54. END AS expensive_event
  55. FROM sys.dm_xe_sessions sess
  56. JOIN sys.dm_xe_session_events evt
  57. ON sess. address = evt.event_session_ address
  58. INNER JOIN sys.trace_xe_event_map xemap
  59. ON evt.event_name = xemap.xe_event_name
  60. GO

步骤 8:配置虚拟机

如果使用的是虚拟机,请确保不会过度预配 CPU 并正确配置它们。
解决 ESX/ESXi 虚拟机性能问题 (2001003)

步骤 9:纵向扩展系统以使用更多 CPU

如果单个查询实例的 CPU 占用很低,但所有查询的总体工作负载共同导致 CPU 占用较高,请考虑通过添加更多 CPU 来纵向扩展计算机。 使用以下查询找出超过单个执行的平均 CPU 占用和最大 CPU 占用的特定阈值且已在系统上多次运行的查询数:


   
   
  1. -- Shows queries where Max and average CPU time exceeds 200 ms and executed more than 1000 times
  2. DECLARE @cputime_threshold_microsec INT = 200 * 1000
  3. DECLARE @execution_ count INT = 1000
  4. SELECT qs.total_worker_ time / 1000 total_cpu_ time_ms,
  5. qs.max_worker_ time / 1000 max_cpu_ time_ms,
  6. (qs.total_worker_ time / 1000) /execution_ count average_cpu_ time_ms,
  7. qs.execution_ count,
  8. q.[text]
  9. FROM sys.dm_exec_query_stats qs CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS q
  10. WHERE (qs.total_worker_ time /execution_ count > @cputime_threshold_microsec
  11. OR qs.max_worker_ time > @cputime_threshold_microsec )
  12. AND execution_ count > @execution_ count
  13. ORDER BY qs.total_worker_ time DESC

三、常用sql检查语句:

1、排查连接对象

此脚本可以查看到主机名和连接对象,如果连接对象不属于已知的软件,在防火墙中将此IP禁止掉即可


   
   
  1. --如果想要指定查询某个数据库,将后面的注释去掉即可
  2. SELECT * FROM sys.[sysprocesses] WHERE [spid] > 50 -- AND DB_NAME([dbid]) = 'hisdb'

2、查询sql阻塞

然后使用下面语句看一下各项指标是否正常,是否有阻塞,正常情况下搜索结果应该为空。


   
   
  1. SELECT [session_id],
  2. [request_id],
  3. [ start_ time] AS '开始时间',
  4. [ status] AS '状态',
  5. [command] AS '命令',
  6. dest.[text] AS 'sql语句',
  7. DB_NAME([database_id]) AS '数据库名',
  8. [blocking_session_id] AS '正在阻塞其他的ID',
  9. [wait_ type] AS '等待资源类型',
  10. [wait_ time] AS '等待时间',
  11. [wait_resource] AS '等待的资源',
  12. [reads] AS '物理读次数',
  13. [writes] AS '写次数',
  14. [logical_reads] AS '逻辑读次数',
  15. [row_ count] AS '返回结果行数'
  16. FROM sys.[dm_exec_requests] AS der
  17. CROSS APPLY
  18. sys.[dm_exec_sql_text](der.[sql_handle]) AS dest
  19. WHERE [session_id] > 50
  20. ORDER BY [cpu_ time] DESC

   
   
  1. ---查看是哪些SQL语句占用较大可以使用下面代码
  2. SELECT TOP 10
  3. dest.[text] AS 'sql语句'
  4. FROM sys.[dm_exec_requests] AS der
  5. CROSS APPLY
  6. sys.[dm_exec_sql_text](der.[sql_handle]) AS dest
  7. WHERE [session_id] > 50
  8. ORDER BY [cpu_ time] DESC

3、查询worker等待

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


   
   
  1. SELECT [session_id],
  2. [request_id],
  3. [ start_ time] AS '开始时间',
  4. [ status] AS '状态',
  5. [command] AS '命令',
  6. dest.[text] AS 'sql语句',
  7. DB_NAME([database_id]) AS '数据库名',
  8. [blocking_session_id] AS '正在阻塞其他的ID',
  9. der.[wait_ type] AS '等待资源类型',
  10. [wait_ time] AS '等待时间',
  11. [wait_resource] AS '等待的资源',
  12. [dows].[waiting_tasks_ count] AS '当前等待任务数',
  13. [reads] AS '物理读次数',
  14. [writes] AS '写次数',
  15. [logical_reads] AS '逻辑读次数',
  16. [row_ count] AS '返回结果行数'
  17. FROM sys.[dm_exec_requests] AS der
  18. INNER JOIN [sys].[dm_os_wait_stats] AS dows
  19. ON der.[wait_ type] =[dows].[wait_ type]
  20. CROSS APPLY
  21. sys.[dm_exec_sql_text](der.[sql_handle]) AS dest
  22. WHERE [session_id] > 50
  23. ORDER BY [cpu_ time] DESC

查询CPU占用最高的SQL语句


   
   
  1. SELECT total_worker_ time /execution_ count AS avg_cpu_cost, plan_handle,
  2. execution_ count,
  3. ( SELECT SUBSTRING(text, statement_ start_offset / 2 + 1,
  4. (CASE WHEN statement_ end_offset = - 1
  5. THEN LEN(CONVERT(nvarchar(max), text)) * 2
  6. ELSE statement_ end_offset
  7. END - statement_ start_offset) / 2)
  8. FROM sys.dm_exec_sql_text(sql_handle)) AS query_text
  9. FROM sys.dm_exec_query_stats
  10. ORDER BY [avg_cpu_cost] DESC

4、索引缺失查询

如果索引缺失的话,需要根据查询结果中的关键信息逐一添加


   
   
  1. SELECT DatabaseName = DB_NAME(database_id)
  2. ,[ Number Indexes Missing] = count( *)
  3. FROM sys.dm_db_missing_ index_details
  4. GROUP BY DB_NAME(database_id)
  5. ORDER BY 2 DESC;
  6. SELECT [Total Cost] = ROUND(avg_total_user_cost * avg_user_impact * (user_seeks + user_scans), 0)
  7. , avg_user_impact
  8. , TableName = statement
  9. , [EqualityUsage] = equality_ columns
  10. , [InequalityUsage] = inequality_ columns
  11. , [Include Cloumns] = included_ columns
  12. FROM sys.dm_db_missing_ index_groups g
  13. INNER JOIN sys.dm_db_missing_ index_ group_stats s ON s. group_handle = g. index_ group_handle
  14. INNER JOIN sys.dm_db_missing_ index_details d ON d. index_handle = g. index_handle
  15. ORDER BY [Total Cost] DESC;

 5、占用cpu高100%排查

sqlserver占用cpu高100%排查,可根据下面语句查询当前耗时最高的sql语句,以及读写次数。


   
   
  1. SELECT TOP 50
  2. [session_id],
  3. [request_id],
  4. [cpu_ time],
  5. [ start_ time] AS '开始时间',
  6. [ status] AS '状态',
  7. [command] AS '命令',
  8. dest.[text] AS 'sql语句',
  9. DB_NAME([database_id]) AS '数据库名',
  10. [blocking_session_id] AS '正在阻塞其他会话的会话ID',
  11. der.[wait_ type] AS '等待资源类型',
  12. [wait_ time] AS '等待时间',
  13. [wait_resource] AS '等待的资源',
  14. [dows].[waiting_tasks_ count] AS '当前正在进行等待的任务数',
  15. [reads] AS '物理读次数',
  16. [writes] AS '写次数',
  17. [logical_reads] AS '逻辑读次数',
  18. [row_ count] AS '返回结果行数'
  19. FROM sys.[dm_exec_requests] AS der
  20. INNER JOIN [sys].[dm_os_wait_stats] AS dows
  21. ON der.[wait_ type] =[dows].[wait_ type]
  22. CROSS APPLY
  23. sys.[dm_exec_sql_text](der.[sql_handle]) AS dest
  24. WHERE [session_id] > 50
  25. ORDER BY [cpu_ time] DESC

 四、其他常用sql


   
   
  1. --------------------SQL Server启动时间
  2. SELECT sqlserver_ start_ time FROM sys.dm_os_sys_info;
  3. --------------------SQL Server版本
  4. select @@version;
  5. --------------------数据库正在执行的sql
  6. select text,wait_resource,wait_ time,wait_ type,session_id,blocking_session_id
  7. from sys.dm_exec_requests cross apply sys.dm_exec_sql_text(sql_handle);
  8. select request_session_id spid, OBJECT_NAME(resource_associated_entity_id) tableName
  9. from sys.dm_tran_locks where resource_ type = 'OBJECT';
  10. --------------------死锁
  11. select a.text seesion_text,a.wait_ type,a.wait_ time,a.session_id,a.blocking_session_id,b.text blocking_session_text from
  12. ( select text,wait_resource,wait_ type,wait_ time,session_id,blocking_session_id from sys.dm_exec_requests
  13. cross apply sys.dm_exec_sql_text(sql_handle) where wait_ time > 1000) a left join
  14. ( select c.session_id,t.text from sys.dm_exec_connections as c cross apply sys.dm_exec_sql_text(most_recent_sql_handle) as t) b
  15. on b.session_id =a.blocking_session_id;
  16. --------------------获取一次性缓存计划的数量
  17. SELECT objtype, cacheobjtype,
  18. AVG(usecounts) AS Avg_UseCount,
  19. SUM(refcounts) AS AllRefObjects,
  20. SUM(CAST( size_ in_bytes AS bigint)) / 1024 / 1024 AS Size_MB
  21. FROM sys.dm_exec_cached_plans
  22. WHERE objtype = 'Adhoc' AND usecounts = 1
  23. GROUP BY objtype, cacheobjtype;
  24. SELECT objtype, cacheobjtype,
  25. AVG(usecounts) AS Avg_UseCount,
  26. SUM(refcounts) AS AllRefObjects,
  27. SUM(CAST( size_ in_bytes AS bigint)) / 1024 / 1024 AS Size_MB
  28. FROM sys.dm_exec_cached_plans
  29. WHERE objtype = 'Adhoc' AND usecounts > 1
  30. GROUP BY objtype, cacheobjtype;
  31. --------------------操作系统内存建议
  32. -- You want to see "Available physical memory is high"
  33. SELECT total_physical_memory_kb / 1024 AS [Physical Memory (MB)],
  34. available_physical_memory_kb / 1024 AS [Available Memory (MB)],
  35. total_ page_ file_kb / 1024 AS [Total Page File (MB)],
  36. available_ page_ file_kb / 1024 AS [Available Page File (MB)],
  37. system_cache_kb / 1024 AS [System Cache (MB)],
  38. system_memory_state_desc AS [System Memory State]
  39. FROM sys.dm_os_sys_memory WITH (NOLOCK) OPTION (RECOMPILE);
  40. --------------------操作系统内存情况
  41. SELECT
  42. physical_memory_ in_ use_kb / 1024 Physical_memory_ in_ use_MB,
  43. large_ page_allocations_kb / 1024 Large_ page_allocations_MB,
  44. locked_ page_allocations_kb / 1024 Locked_ page_allocations_MB,
  45. virtual_ address_ space_reserved_kb / 1024 VAS_reserved_MB,
  46. virtual_ address_ space_committed_kb / 1024 VAS_committed_MB,
  47. virtual_ address_ space_available_kb / 1024 VAS_available_MB,
  48. page_fault_ count Page_fault_ count,
  49. memory_utilization_percentage Memory_utilization_percentage,
  50. process_physical_memory_low Process_physical_memory_low,
  51. process_virtual_memory_low Process_virtual_memory_low
  52. FROM sys.dm_os_process_memory;
  53. --------------------恢复日志描述模型,复用等,日志大小和日志文件大小
  54. SELECT db.[name] AS [Database Name], SUSER_SNAME(db.owner_sid) AS [Database Owner], db.recovery_model_desc AS [Recovery Model],
  55. db.log_reuse_wait_desc AS [Log Reuse Wait Description],
  56. CAST((CAST(ls.cntr_ value AS FLOAT) / 1024) AS DECIMAL( 18,2)) AS [Log Size (MB)],
  57. CAST((CAST(lu.cntr_ value AS FLOAT) / 1024) AS DECIMAL( 18,2)) AS [Log Used (MB)],
  58. CAST(CAST(lu.cntr_ value AS FLOAT) / CAST(ls.cntr_ value AS FLOAT) AS DECIMAL( 18,2)) * 100 AS [Log Used %],
  59. db.[compatibility_level] AS [DB Compatibility Level],
  60. db. page_verify_option_desc AS [ Page Verify Option],db. is_auto_update_stats_ on,
  61. db. is_auto_update_stats_async_ on,
  62. db. is_auto_ close_ on, db. is_auto_shrink_ on
  63. FROM sys.databases AS db WITH (NOLOCK)
  64. INNER JOIN sys.dm_os_performance_counters AS lu WITH (NOLOCK)
  65. ON db.name = lu.instance_name
  66. INNER JOIN sys.dm_os_performance_counters AS ls WITH (NOLOCK)
  67. ON db.name = ls.instance_name
  68. WHERE lu.counter_name LIKE N 'Log File(s) Used Size (KB)%'
  69. AND ls.counter_name LIKE N 'Log File(s) Size (KB)%'
  70. AND ls.cntr_ value > 0
  71. ORDER BY db.[name] OPTION (RECOMPILE);
  72. --------------------按索引优势列出的所有数据库缺少索引
  73. SELECT CONVERT(decimal( 18,2), user_seeks * avg_total_user_cost * (avg_user_impact * 0.01)) AS [ index_advantage],
  74. migs. last_user_seek, mid.[statement] AS [Database.Schema. Table],
  75. mid.equality_ columns, mid.inequality_ columns, mid.included_ columns,
  76. migs.unique_compiles, migs.user_seeks, migs.avg_total_user_cost, migs.avg_user_impact
  77. FROM sys.dm_db_missing_ index_ group_stats AS migs WITH (NOLOCK)
  78. INNER JOIN sys.dm_db_missing_ index_groups AS mig WITH (NOLOCK)
  79. ON migs. group_handle = mig. index_ group_handle
  80. INNER JOIN sys.dm_db_missing_ index_details AS mid WITH (NOLOCK)
  81. ON mig. index_handle = mid. index_handle
  82. ORDER BY index_advantage DESC OPTION (RECOMPILE);
  83. --------------------查看CPU占用量最高的会话及SQL语句
  84. select spid,cmd,cpu,physical_io,memusage,
  85. ( select top 1 [text] from ::fn_ get_sql(sql_handle)) sql_text
  86. from master..sysprocesses order by cpu desc,physical_io desc
  87. --------------------查看缓存重用次数少,内存占用大的SQL语句
  88. SELECT TOP 100 usecounts, objtype, p. size_ in_bytes,[sql].[text]
  89. FROM sys.dm_exec_cached_plans p OUTER APPLY sys.dm_exec_sql_text (p.plan_handle) sql
  90. ORDER BY usecounts,p. size_ in_bytes desc
  91. --------------------查看哪些进程在使用
  92. select * from sysprocesses
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值