Exécution de notre entreprise ERP (Dynamics AX 2012), j'ai remarqué que notre environnement de production semblait beaucoup plus lent que nos systèmes de développement.
Après avoir effectué les mêmes activités dans les environnements de développement et de production tout en exécutant une trace, j'ai confirmé que les requêtes SQL exécutant très lentement sur notre environnement de production par rapport au développement (10-50x plus ralentissent en moyenne).
Au début, j'ai attribué cela pour charger et réaffecter les mêmes activités sur l'environnement de production pendant les heures d'arrêt et ont trouvé les mêmes résultats dans la trace.
J'ai effacé mes statistiques d'attente dans SQL Server, puis laissez le serveur exécuter sous sa charge de production normale pendant un peu de temps, puis a exécuté cette requête:
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
Mes résultats sont les suivants:
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
Donc, apparemment, la plus grande attente est Sos_scheduler_yield de loin, et j'ai googlé et j'ai constaté que cela se rapporte généralement à la CPU ne pouvant pas continuer à suivre.
J'ai ensuite couru cette requête plusieurs fois de suite.
SELECT *
FROM sys.dm_os_schedulers
WHERE scheduler_id < 255
Je sais que je suis censé chercher des planificateurs avec non-zéro runnable_tasks_count ou pender_disk_io_count, mais c'est fondamentalement zéro presque tout le temps.
Je devrais également mentionner que Max degré de parallélisme était défini sur 1, car la charge de travail Dynamics AX a-t-elle typiquement OLTP dans la nature et la modification de 8 n'a pas fait beaucoup de différence dans les statistiques attendues ci-dessus, Ils sont devenus presque exactement les mêmes problèmes de performance.
Je suis une sorte de perte d'où aller d'ici, j'ai essentiellement un serveur SQL qui appartient à la CPU, mais pas d'attente sur Runnable_Tasks ou io.
Je sais que le IO Subsystème de ce serveur SQL n'est pas très bon, car exécuter SQLIO sur le lecteur contenant les bases de données réelles peut conduire à des nombres assez bas (penser à 10 Mo d'une seconde pour certains types. des lectures/écriture), cela dit, il ne semble pas que SQL soit attendu à ce sujet en raison de la quantité de mémoire sur le serveur en cache la plupart des bases de données.
Voici quelques informations sur l'environnement pour aider:
Environnement de production:
Mon dev:
Je souhaiterais une contribution sur d'autres choses à rechercher.
Donc, j'ai résolu cela, ce qui éteint que les fonctions de gestion de l'alimentation ont été activées sur notre serveur SQL qui permettent de réduire la fréquence de la CPU de haut en bas, mais pas suffisamment rapidement pour suivre la petite demande et introduirez le SOS_SCHEDULER_YILIOND. Après le remplacer pour courir toujours en haute performance, le problème s'est éloigné et les attentes sont plus normales (type de type Latchio).