Gestendo il nostro ERP aziendale (Dynamics AX 2012), ho notato che il nostro ambiente di produzione sembrava molto più lento dei nostri sistemi di sviluppo.
Dopo aver eseguito le stesse attività negli ambienti di sviluppo e produzione durante l'esecuzione di una traccia, ho confermato che le query SQL venivano eseguite molto lentamente nel nostro ambiente di produzione rispetto allo sviluppo (in media 10-50 volte più lento).
Inizialmente l'ho attribuito al caricamento e ho eseguito nuovamente le stesse attività sull'ambiente di produzione durante le ore di inattività e ho trovato gli stessi risultati nella traccia.
Ho cancellato le mie statistiche di attesa in SQL Server, quindi ho lasciato il server sotto il suo normale carico di produzione per un po ', quindi ho eseguito questa query:
WITH [Waits] AS
(SELECT
[wait_type],
[wait_time_ms] / 1000.0 AS [WaitS],
([wait_time_ms] - [signal_wait_time_ms]) / 1000.0 AS [ResourceS],
[signal_wait_time_ms] / 1000.0 AS [SignalS],
[waiting_tasks_count] AS [WaitCount],
100.0 * [wait_time_ms] / SUM ([wait_time_ms]) OVER() AS [Percentage],
ROW_NUMBER() OVER(ORDER BY [wait_time_ms] DESC) AS [RowNum]
FROM sys.dm_os_wait_stats
WHERE [wait_type] NOT IN (
N'CLR_SEMAPHORE', N'LAZYWRITER_SLEEP',
N'RESOURCE_QUEUE', N'SQLTRACE_BUFFER_FLUSH',
N'SLEEP_TASK', N'SLEEP_SYSTEMTASK',
N'WAITFOR', N'HADR_FILESTREAM_IOMGR_IOCOMPLETION',
N'CHECKPOINT_QUEUE', N'REQUEST_FOR_DEADLOCK_SEARCH',
N'XE_TIMER_EVENT', N'XE_DISPATCHER_JOIN',
N'LOGMGR_QUEUE', N'FT_IFTS_SCHEDULER_IDLE_WAIT',
N'BROKER_TASK_STOP', N'CLR_MANUAL_EVENT',
N'CLR_AUTO_EVENT', N'DISPATCHER_QUEUE_SEMAPHORE',
N'TRACEWRITE', N'XE_DISPATCHER_WAIT',
N'BROKER_TO_FLUSH', N'BROKER_EVENTHANDLER',
N'FT_IFTSHC_MUTEX', N'SQLTRACE_INCREMENTAL_FLUSH_SLEEP',
N'DIRTY_PAGE_POLL', N'SP_SERVER_DIAGNOSTICS_SLEEP')
)
SELECT
[W1].[wait_type] AS [WaitType],
CAST ([W1].[WaitS] AS DECIMAL(14, 2)) AS [Wait_S],
CAST ([W1].[ResourceS] AS DECIMAL(14, 2)) AS [Resource_S],
CAST ([W1].[SignalS] AS DECIMAL(14, 2)) AS [Signal_S],
[W1].[WaitCount] AS [WaitCount],
CAST ([W1].[Percentage] AS DECIMAL(4, 2)) AS [Percentage],
CAST (([W1].[WaitS] / [W1].[WaitCount]) AS DECIMAL (14, 4)) AS [AvgWait_S],
CAST (([W1].[ResourceS] / [W1].[WaitCount]) AS DECIMAL (14, 4)) AS [AvgRes_S],
CAST (([W1].[SignalS] / [W1].[WaitCount]) AS DECIMAL (14, 4)) AS [AvgSig_S]
FROM [Waits] AS [W1] INNER JOIN [Waits] AS [W2] ON [W2].[RowNum] <= [W1].[RowNum]
GROUP BY [W1].[RowNum], [W1].[wait_type], [W1].[WaitS],
[W1].[ResourceS], [W1].[SignalS], [W1].[WaitCount], [W1].[Percentage]
HAVING SUM ([W2].[Percentage]) - [W1].[Percentage] < 95; -- percentage threshold
I miei risultati sono i seguenti:
WaitType Wait_S Resource_S Signal_S WaitCount Percentage AvgWait_S AvgRes_S AvgSig_S
SOS_SCHEDULER_YIELD 4162.52 3.64 4158.88 4450085 77.33 0.0009 0.0000 0.0009
ASYNC_NETWORK_IO 457.98 331.59 126.39 351113 8.51 0.0013 0.0009 0.0004
PAGELATCH_EX 252.94 5.14 247.80 796348 4.70 0.0003 0.0000 0.0003
WRITELOG 166.01 48.01 118.00 302209 3.08 0.0005 0.0002 0.0004
LCK_M_U 145.47 145.45 0.02 123 2.70 1.1827 1.1825 0.0002
Quindi apparentemente il più grande Wait è SOS_Scheduler_Yield di gran lunga, e ho cercato su Google e ho scoperto che in genere si riferisce alla CPU che non è in grado di tenere il passo.
Ho quindi eseguito questa query più volte in successione.
SELECT *
FROM sys.dm_os_schedulers
WHERE scheduler_id < 255
So che dovrei cercare programmatori con runnable_tasks_count diverso da zero o pending_disk_io_count, ma è praticamente zero quasi sempre.
Devo anche menzionare che Max Degree of Parallelism era impostato su 1, poiché il carico di lavoro di Dynamics AX è in genere di tipo OLTP, e cambiarlo 8 non ha fatto molta differenza nelle statistiche di attesa sopra, sono diventate quasi identiche con lo stesso problemi di prestazioni.
Sono quasi a corto di dove andare da qui, fondamentalmente ho un SQL Server che è apparentemente legato alla CPU ma non aspetta runnable_tasks o IO.
So che il sottosistema IO di questo SQL Server non è molto buono, perché l'esecuzione di SQLIO sull'unità contenente i database effettivi può portare a numeri piuttosto bassi (si pensi a 10 MB al secondo per alcuni tipi di letture / scritture), che diceva: non sembra che SQL lo stia aspettando a causa della quantità di memoria sul server che memorizza nella cache la maggior parte dei database.
Ecco alcune informazioni sull'ambiente per aiutare:
Ambiente di produzione:
- server SQL
- HP ProLian DL360p Gen8
- Intel Xeon E5-2650 0 a 2,00 GHz x 2 con hyperthreading (32 core logici)
- 184 GB di memoria
- Windows Server 2012
- 2 istanze di SQL Server 2012 Standard (RTM, senza patch)
- Raid 1 unità da 279 GB (15k) C: unità, contiene database e sistema operativo
- File di paging e TempDB su unità distinte e separate (stato solido)
Il mio DEV:
- Hyper-V ha ospitato SQL Server e Dynamics AX 2012 AOS server
- Core i7 3.4ghz con hyperthreading (8 core logici)
- 8 GB di memoria
- Windows Server 2008 R2
- SSD per l'intera macchina virtuale.
Gradirei qualsiasi input su altre cose da cercare.