A friend asked me to help him look at the database, the operating system is Windows 2008 R2, the database is SQL 2008 R2 64 bits. Hardware configuration is still relatively high, 64G memory, 16-core CPU, he said that the server is running Kingdee K3 software, database instances there are multiple databases.
phenomenon
He said that these days only appeared, but also will be high CPU utilization occurs at a certain time each day
Memory usage is not too high, only takes 30 G
100% CPU utilization
The direction of the investigation
General investigation are with the following script, usually used three views sys.sysprocesses, dm_exec_sessions, dm_exec_requests
1
2
3
4
5
USE master
GO
- If you want to specify the database took remove comments
SELECT * FROM sys.[sysprocesses] WHERE [spid]>50 --AND DB_NAME([dbid])="gposdb"
SELECT COUNT(*) FROM [sys].[dm_exec_sessions] WHERE [session_id]>50
Look at the current database user connections number
Then use the following statement to look at the indicators are normal, whether there is obstruction, this statement is selected sessions of the top 10 most CPU time consuming
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
SELECT TOP 10
[session_id],
[request_id],
[Start_time] AS "start time"
[Status] AS "Status",
[command] AS "命令",
dest.[text] AS "sql语句",
DB_NAME ([database_id]) AS "database name"
[Blocking_session_id] AS "session ID blocking other sessions"
[Wait_type] AS "waiting for resource type"
[Wait_time] AS "waiting time"
[Wait_resource] AS "resource waiting"
[Reads] AS "number of physical reads"
[Writes] AS "write the number"
[Logical_reads] AS "number of logical reads"
[Row_count] AS "Returns the number of rows in the result"
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
If you want to see a specific SQL statement can execute the following SQL statement, remember to choose to display the results in text format in SSMS
1
2
3
4
5
6
7
- Select SSMS results in display in text format
SELECT TOP 10
dest.[text] AS "sql语句"
FROM sys.[dm_exec_requests] AS der
CROSS APPLY
sys.[dm_exec_sql_text](der.[sql_handle]) AS dest WHERE [session_id]>50
ORDER BY [cpu_time] DESC
Mimics some of the operation of CPU time consumption
There are several viewing CPU scheduler, and user number and the maximum number of worker threads, to check whether the worker can also run out of CPU utilization investigation
1
2
3
4
- Check the number of CPU scheduler, and user number
SELECT cpu_count,scheduler_count FROM sys.dm_os_sys_info
- The maximum number of worker threads View
SELECT max_workers_count FROM sys.dm_os_sys_info
View all schedulers on the machine, including user and system
The following statement can be seen whether the worker runs out, when the maximum number of threads necessary to check the blocking
The following comparison table
The maximum number of worker threads various combinations of CPU and SQLSERVER version autoconfiguration
Number of 32-bit computer CPU 64 computer
<=4 256 512
8 288 576
16 352 704
32 480 960
1
2
3
4
5
6
7
8
SELECT
scheduler_address,
scheduler_id,
cpu_id,
status,
current_tasks_count,
current_workers_count,active_workers_count
FROM sys.dm_os_schedulers
If there is a resource SQLSERVER to wait, then execute the following statement will show how many sessions worker waiting
Combined with [sys]. [Dm_os_wait_stats] view, if the current SQLSERVER there is no waiting for a resource, then the following SQL statement does not show any results
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
SELECT TOP 10
[session_id],
[request_id],
[Start_time] AS "start time"
[Status] AS "Status",
[command] AS "命令",
dest.[text] AS "sql语句",
DB_NAME ([database_id]) AS "database name"
[Blocking_session_id] AS "session ID blocking other sessions"
der. [wait_type] AS "waiting for resource type"
[Wait_time] AS "waiting time"
[Wait_resource] AS "resource waiting"
[Dows]. [Waiting_tasks_count] AS "number of tasks currently in progress waiting"
[Reads] AS "number of physical reads"
[Writes] AS "write the number"
[Logical_reads] AS "number of logical reads"
[Row_count] AS "Returns the number of rows in the result"
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
For example, I currently executing the query SalesOrderDetail_test table 100, due to the very large table of data, so the results need to SSMS SQLSERVER performed slowly removed,
Caused ASYNC_NETWORK_IO wait
1
2
3
4
USE [AdventureWorks]
GO
SELECT * FROM dbo.[SalesOrderDetail_test]
GO 100
Source of the problem
Through observation and investigation of the case these days, is to determine the cause of some tables are missing indexes, now adds indexes on these tables, problem solving
1
2
3
4
5
6
select * from t_AccessControl - access control list access control
select * from t_GroupAccess - user group permissions user group permissions table
select * from t_GroupAccessType - user group permissions user group permissions class class table
select * from t_ObjectAccess - object privileges table object privileges
select * from t_ObjectAccessType - the type of object permissions table object permission type
select * from t_ObjectType - object type object type table
High CPU usage query statement
1
2
3
4
5
6
7
8
9
10
11
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
Missing index query
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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;
(View larger image)
After locating the problem, a new non-clustered index
1
2
3
4
5
6
7
CREATE NONCLUSTERED INDEX IX_t_AccessControl_F4 ON dbo.t_AccessControl
(
FObjectType
)include([FUserID], [FAccessType], [FAccessMask]) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
drop index IX_t_AccessControl_F4 on t_AccessControl
CPU usage is back to normal
Tracking template and trace files to download, use SQL2008R2 version: files.cnblogs.com/lyhabc/ tracking templates and trace.rar
to sum up
From historical experience, many times, if sustained high CPU load, memory and IO are okay but then, in this case, the first thought must be the index of the problem, in all likelihood can not go wrong.
Note that at the beginning of the article posted on the client machine load chart