Cad*_*oux 9 sql-server wait-types
我在 VM 中有一个共享的 SQL Server 2016 开发实例,与(应该是)相同 VM 上的共享 SQL Server 2012 开发实例相比,该实例的 INSERT 性能较差。它与我的本地 SQL Server 2016 开发实例相比也很差,因此我目前假设该实例存在一些古怪的问题,因为该服务器上的大多数其他操作似乎相当稳定。
它们是以下形式的 1000 个单独的插入语句:
INSERT INTO tblname (columnlist) VALUES (literals);
没有明确的交易。
我将这些 INSERT 包装在扩展事件中,以便我可以看到一些环境之间的差异。我还制作了一个运行循环而不是文字的版本。循环的性能在受影响的系统上明显不同,我不包括下面的循环版本代码 - 它执行一致,但在执行该脚本之前我确实删除并重新创建了数据库,结果也包括在内。
我已将系统设置为可重现并轻松推送到任何系统进行比较。我正在运行命令脚本和 sqlcmd 中的所有内容。首先运行安装脚本以创建数据库、表和 XE 会话。然后运行第二个脚本,启动跟踪,执行 1000 条 INSERT VALUES 语句,停止跟踪并使用https://www.sqlskills.com/blogs/paul/capturing-wait-stats-for-a-single-显示结果手术/
我已经注意到这个特定的 SQL Server 2016 在 SOS_SCHEDULER_YIELD 周围有非常不同的特征,我想知道这是否已经指出潜在的问题可能是什么。此外,我似乎已将此问题与在此服务器上的默认值中使用 GETDATE 和 GETUTCDATE 隔离开来。
性能测试.cmd:
DEL *.xel
echo Running setup.sql
sqlcmd -o "setup.sql.output-1.txt" -I -b -l 120 -t 300 -S %SQLINSTANCE% -U sa -P %PASSWORD% -d master -i .\setup.sql
echo Running perftest.sql
sqlcmd -o "perftest.sql.output-1.txt" -I -b -l 120 -t 300 -S %SQLINSTANCE% -U sa -P %PASSWORD% -d InsertPerfTest -i .\perftest.sql
echo Running setup.sql
sqlcmd -o "setup.sql.output-2.txt" -I -b -l 120 -t 300 -S %SQLINSTANCE% -U sa -P %PASSWORD% -d master -i .\setup.sql
echo Running perftestloop.sql
sqlcmd -o "perftestloop.sql.output-1.txt" -I -b -l 120 -t 300 -S %SQLINSTANCE% -U sa -P %PASSWORD% -d InsertPerfTest -i .\perftestloop.sql
COPY setup.sql.output-1.txt /A + perftest.sql.output-1.txt /A + setup.sql.output-2.txt /A + perftestloop.sql.output-1.txt /A combined-output.txt /A
Run Code Online (Sandbox Code Playgroud)
设置.sql:
SET NOCOUNT ON;
GO
PRINT '-------------------- SCRIPT START--------------------------------';
SELECT TEST = 'setup.sql', SERVERNAME = CAST(@@SERVERNAME AS nvarchar(32)), [VERSION] = @@VERSION, DATABASENAME = CAST(DB_NAME() AS nvarchar(32));
GO
IF EXISTS (SELECT * FROM sys.databases WHERE [name] = 'InsertPerfTest')
BEGIN
EXEC msdb.dbo.sp_delete_database_backuphistory @database_name = N'InsertPerfTest';
ALTER DATABASE [InsertPerfTest] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
DROP DATABASE [InsertPerfTest];
END
GO
CREATE DATABASE [InsertPerfTest]
ON (
NAME = 'PerfTest_Data'
, FILENAME = 'C:\perftest\PerfTest_Data.mdf'
, SIZE = 32MB
, MAXSIZE = 32MB
)
LOG ON (
NAME = 'PerfTest_Log'
, FILENAME = 'C:\perftest\PerfTest_Log.ldf'
, SIZE = 32MB
, MAXSIZE = 32MB
)
;
GO
ALTER DATABASE [InsertPerfTest] SET RECOVERY SIMPLE;
GO
USE [InsertPerfTest];
GO
ALTER DATABASE SCOPED CONFIGURATION SET MAXDOP = 1;
GO
CREATE TABLE [TrivialTest](
[MapRowID] [int] IDENTITY(1,1) NOT NULL,
[ItemNumber] [int] NOT NULL,
[ItemText] [nvarchar](max) NULL,
[UpdateDateTime] [datetimeoffset](7) NOT NULL CONSTRAINT [DF_Trivial_UpdateDateTime] DEFAULT (GETUTCDATE())
);
GO
CREATE TABLE [TrivialTest2](
[MapRowID] [int] IDENTITY(1,1) NOT NULL,
[ItemNumber] [int] NOT NULL,
[ItemText] [nvarchar](max) NULL,
[UpdateDateTime] [datetimeoffset](7) NOT NULL CONSTRAINT [DF_Trivial2_UpdateDateTime] DEFAULT ('01/01/1970')
);
GO
CREATE TABLE [TrivialTest3](
[MapRowID] [int] IDENTITY(1,1) NOT NULL,
[ItemNumber] [int] NOT NULL,
[ItemText] [nvarchar](max) NULL,
[UpdateDateTime] [datetimeoffset](7) NOT NULL CONSTRAINT [DF_Trivial3_UpdateDateTime] DEFAULT (GETDATE())
);
GO
IF EXISTS (SELECT * FROM sys.server_event_sessions WHERE name = 'MonitorWaits')
DROP EVENT SESSION MonitorWaits ON SERVER;
GO
CREATE EVENT SESSION MonitorWaits ON SERVER
ADD EVENT sqlos.wait_info
(WHERE sqlserver.database_name = 'InsertPerfTest')
ADD TARGET package0.asynchronous_file_target
(SET FILENAME = N'C:\perftest\EE_WaitStats.xel',
METADATAFILE = N'C:\perftest\EE_WaitStats.xem')
WITH (max_dispatch_latency = 1 seconds);
GO
Run Code Online (Sandbox Code Playgroud)
性能测试.sql:
SET NOCOUNT ON;
GO
PRINT '-------------------- SCRIPT START--------------------------------';
SELECT TEST = 'perftest.sql', SERVERNAME = CAST(@@SERVERNAME AS nvarchar(32)), [VERSION] = @@VERSION, DATABASENAME = CAST(DB_NAME() AS nvarchar(32));
TRUNCATE TABLE [TrivialTest];
TRUNCATE TABLE [TrivialTest2];
TRUNCATE TABLE [TrivialTest3];
SELECT RowsExistingTest = (SELECT COUNT(*) FROM [TrivialTest])
, RowsExistingTest2 = (SELECT COUNT(*) FROM [TrivialTest2])
, RowsExistingTest3 = (SELECT COUNT(*) FROM [TrivialTest3]);
GO
ALTER EVENT SESSION MonitorWaits ON SERVER STATE = START;
GO
DECLARE @ResultsMS AS TABLE(SetName nvarchar(50) NOT NULL, TimeMS int NOT NULL);
DECLARE @Start AS DATETIME;
DECLARE @End AS DATETIME;
SET @Start = GETDATE();
INSERT INTO TrivialTest (ItemNumber, [ItemText]) VALUES ('1', 'Put a huge lump of text here, not sure it really matters, but we want to get the rows size up to a size that''s similar to what we are seeing in the real world rule set.');
-- ... Another 998 rows here
INSERT INTO TrivialTest (ItemNumber, [ItemText]) VALUES ('1000', 'Put a huge lump of text here, not sure it really matters, but we want to get the rows size up to a size that''s similar to what we are seeing in the real world rule set.');
SET @End = GETDATE();
INSERT INTO @ResultsMS (SetName, TimeMS)
SELECT 'Set 1: GETUTCDATE', DATEDIFF(MILLISECOND, @Start, @End);
SET @Start = GETDATE();
INSERT INTO TrivialTest2 (ItemNumber, [ItemText]) VALUES ('1', 'Put a huge lump of text here, not sure it really matters, but we want to get the rows size up to a size that''s similar to what we are seeing in the real world rule set.');
-- ... Another 998 rows here
INSERT INTO TrivialTest2 (ItemNumber, [ItemText]) VALUES ('1000', 'Put a huge lump of text here, not sure it really matters, but we want to get the rows size up to a size that''s similar to what we are seeing in the real world rule set.');
SET @End = GETDATE();
INSERT INTO @ResultsMS (SetName, TimeMS)
SELECT 'Set 2: Literal', DATEDIFF(MILLISECOND, @Start, @End);
SET @Start = GETDATE();
INSERT INTO TrivialTest3 (ItemNumber, [ItemText]) VALUES ('1', 'Put a huge lump of text here, not sure it really matters, but we want to get the rows size up to a size that''s similar to what we are seeing in the real world rule set.');
-- ... Another 998 rows here
INSERT INTO TrivialTest3 (ItemNumber, [ItemText]) VALUES ('1000', 'Put a huge lump of text here, not sure it really matters, but we want to get the rows size up to a size that''s similar to what we are seeing in the real world rule set.');
SET @End = GETDATE();
INSERT INTO @ResultsMS (SetName, TimeMS)
SELECT 'Set 3: GETDATE', DATEDIFF(MILLISECOND, @Start, @End);
SELECT *
FROM @ResultsMS
ORDER BY SetName;
GO
ALTER EVENT SESSION MonitorWaits ON SERVER STATE = STOP;
GO
SELECT RowsExistingTest = (SELECT COUNT(*) FROM [TrivialTest])
, RowsExistingTest2 = (SELECT COUNT(*) FROM [TrivialTest2])
, RowsExistingTest3 = (SELECT COUNT(*) FROM [TrivialTest3]);
GO
-- https://www.sqlskills.com/blogs/paul/capturing-wait-stats-for-a-single-operation/
--Create intermediate temp table for raw event data
CREATE TABLE #RawEventData (
Rowid INT IDENTITY PRIMARY KEY,
event_data XML);
GO
-- Read the file data into intermediate temp table
INSERT INTO #RawEventData (event_data)
SELECT
CAST (event_data AS XML) AS event_data
FROM sys.fn_xe_file_target_read_file (
'C:\perftest\EE_WaitStats*.xel',
'C:\perftest\EE_WaitStats*.xem', null, null);
GO
SELECT
waits.[Wait Type],
COUNT (*) AS [Wait Count],
SUM (waits.[Duration]) AS [Total Wait Time (ms)],
SUM (waits.[Duration]) - SUM (waits.[Signal Duration]) AS [Total Resource Wait Time (ms)],
SUM (waits.[Signal Duration]) AS [Total Signal Wait Time (ms)]
FROM
(SELECT
event_data.value ('(/event/@timestamp)[1]', 'DATETIME') AS [Time],
event_data.value ('(/event/data[@name=''wait_type'']/text)[1]', 'VARCHAR(25)') AS [Wait Type],
event_data.value ('(/event/data[@name=''opcode'']/text)[1]', 'VARCHAR(100)') AS [Op],
event_data.value ('(/event/data[@name=''duration'']/value)[1]', 'BIGINT') AS [Duration],
event_data.value ('(/event/data[@name=''signal_duration'']/value)[1]', 'BIGINT') AS [Signal Duration]
FROM #RawEventData
) AS waits
WHERE waits.[op] = 'End'
GROUP BY waits.[Wait Type]
ORDER BY [Total Wait Time (ms)] DESC;
GO
-- Cleanup
DROP TABLE #RawEventData;
GO
Run Code Online (Sandbox Code Playgroud)
组合输出.txt:
-------------------- SCRIPT START--------------------------------
TEST SERVERNAME VERSION DATABASENAME
--------- -------------------------------- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ --------------------------------
setup.sql SQL2016DEV Microsoft SQL Server 2016 (SP2-GDR) (KB4532097) - 13.0.5102.14 (X64)
Dec 31 2019 22:39:35
Copyright (c) Microsoft Corporation
Standard Edition (64-bit) on Windows Server 2012 R2 Standard 6.3 <X64> (Build 9600: ) (Hypervisor)
master
Changed database context to 'InsertPerfTest'.
-------------------- SCRIPT START--------------------------------
TEST SERVERNAME VERSION DATABASENAME
------------ -------------------------------- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ --------------------------------
perftest.sql SQL2016DEV Microsoft SQL Server 2016 (SP2-GDR) (KB4532097) - 13.0.5102.14 (X64)
Dec 31 2019 22:39:35
Copyright (c) Microsoft Corporation
Standard Edition (64-bit) on Windows Server 2012 R2 Standard 6.3 <X64> (Build 9600: ) (Hypervisor)
InsertPerfTest
RowsExistingTest RowsExistingTest2 RowsExistingTest3
---------------- ----------------- -----------------
0 0 0
SetName TimeMS
-------------------------------------------------- -----------
Set 1: GETUTCDATE 31920
Set 2: Literal 877
Set 3: GETDATE 31890
RowsExistingTest RowsExistingTest2 RowsExistingTest3
---------------- ----------------- -----------------
1000 1000 1000
Wait Type Wait Count Total Wait Time (ms) Total Resource Wait Time (ms) Total Signal Wait Time (ms)
------------------------- ----------- -------------------- ----------------------------- ---------------------------
WRITELOG 3001 1276 1274 2
SOS_SCHEDULER_YIELD 2066 61 2 59
PAGEIOLATCH_SH 1 2 2 0
PAGELATCH_SH 2 0 0 0
NETWORK_IO 38 0 0 0
XE_BUFFERMGR_ALLPROCESSED 1 0 0 0
PAGELATCH_EX 2 0 0 0
-------------------- SCRIPT START--------------------------------
TEST SERVERNAME VERSION DATABASENAME
--------- -------------------------------- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ --------------------------------
setup.sql SQL2016DEV Microsoft SQL Server 2016 (SP2-GDR) (KB4532097) - 13.0.5102.14 (X64)
Dec 31 2019 22:39:35
Copyright (c) Microsoft Corporation
Standard Edition (64-bit) on Windows Server 2012 R2 Standard 6.3 <X64> (Build 9600: ) (Hypervisor)
master
Changed database context to 'InsertPerfTest'.
-------------------- SCRIPT START--------------------------------
TEST SERVERNAME VERSION DATABASENAME
---------------- -------------------------------- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ --------------------------------
perftestloop.sql SQL2016DEV Microsoft SQL Server 2016 (SP2-GDR) (KB4532097) - 13.0.5102.14 (X64)
Dec 31 2019 22:39:35
Copyright (c) Microsoft Corporation
Standard Edition (64-bit) on Windows Server 2012 R2 Standard 6.3 <X64> (Build 9600: ) (Hypervisor)
InsertPerfTest
RowsExistingTest RowsExistingTest2 RowsExistingTest3
---------------- ----------------- -----------------
0 0 0
SetName TimeMS
-------------------------------------------------- -----------
Set 1: GETUTCDATE 940
Set 2: Literal 796
Set 3: GETDATE 1030
RowsExistingTest RowsExistingTest2 RowsExistingTest3
---------------- ----------------- -----------------
1000 1000 1000
Wait Type Wait Count Total Wait Time (ms) Total Resource Wait Time (ms) Total Signal Wait Time (ms)
------------------------- ----------- -------------------- ----------------------------- ---------------------------
WRITELOG 6002 1798 1792 6
SOS_SCHEDULER_YIELD 2069 61 2 59
PAGEIOLATCH_SH 2 2 2 0
XE_BUFFERMGR_ALLPROCESSED 2 1 1 0
PAGELATCH_EX 4 0 0 0
PAGELATCH_SH 4 0 0 0
NETWORK_IO 38 0 0 0
Run Code Online (Sandbox Code Playgroud)
Fra*_*ani -4
SOS_SCHEDULER_YIELD表示您\xe2\x80\x99 已发生争用,并且查询花费了大量时间等待访问 CPU。
另一个测试:将 2016 年降级compatibility level到 2012 年,看看执行是否需要几秒钟。它可能与 2016 年使用的基数有关。