Il pourrait également être utile de travailler sur un exemple. Considérez les trois états les plus courants pour un travailleur :
RUNNING = Worker s'exécute actuellement de manière non préventive ou préventive.
RUNNABLE = Le travailleur est prêt à s'exécuter sur le planificateur.
SUSPENDED = Le travailleur est actuellement suspendu, en attente d'un événement pour lui envoyer un signal.
Les travailleurs avec un état de RUNNING
peuvent générer des temps d'attente. Par exemple, si le travailleur doit exécuter du code dans le système d'exploitation plutôt que dans SQLOS, il peut entrer une attente préemptive ou externe. Pendant ce temps, il exécutera du code sur son processeur associé, mais générera toujours du temps d'attente.
Les travailleurs avec un état de RUNNABLE
peuvent générer des temps d'attente (pour autant que je sache, ils le font toujours). Si le travailleur a été informé qu'une ressource était disponible, il peut accumuler le temps d'attente du signal en fonction de la dernière attente. Si le travailleur a épuisé son quantum précédent de 4 ms, il peut accumuler du SOS_SCHEDULER_YIELD
temps d'attente.
Les travailleurs avec un état de SUSPENDED
peuvent générer des temps d'attente. Considérez un travailleur qui attend un verrou. Il générera un temps d'attente jusqu'à ce qu'il soit signalé que la ressource de verrouillage dont il a besoin est disponible. Certains travailleurs suspendus ne génèrent pas de temps d'attente, y compris ceux qui ne sont pas associés à une tâche.
Mon bureau a quatre cœurs logiques, donc le nombre maximal de travailleurs par défaut est 512 . C'est presque certainement impossible, mais sur cette machine, je pourrais théoriquement générer 512 secondes de temps d'attente par seconde si je réussissais à faire en sorte que chaque travailleur attende quelque chose à la fois. Au fur et à mesure que le nombre de noyaux / travailleurs augmente, ce nombre peut devenir encore plus élevé.
Vous pouvez voir plus d'une seconde d'attente par seconde même si vous n'exécutez aucune requête sur SQL Server. Sur ma machine, la requête suivante semble générer entre 9 et 14 lignes:
SELECT [state], last_wait_type, wait_started_ms_ticks
FROM sys.dm_os_workers
WHERE [state] IN ('SUSPENDED', 'RUNNABLE')
AND task_address IS NOT NULL
AND wait_started_ms_ticks <> 0
AND wait_started_ms_ticks >= start_quantum;
Je peux prendre un instantané du temps d'attente total depuis le dernier redémarrage du serveur et le comparer à un nouveau total après avoir attendu dix secondes:
DECLARE @start_wait_time_ms BIGINT;
SELECT @start_wait_time_ms = SUM(wait_time_ms)
FROM sys.dm_os_wait_stats
WHERE wait_type <> 'WAITFOR';
WAITFOR DELAY '00:00:10';
SELECT SUM(wait_time_ms) - @start_wait_time_ms
FROM sys.dm_os_wait_stats
WHERE wait_type <> 'WAITFOR';
Parfois, les mathématiques fonctionnent. La dernière fois que je l'ai exécuté, le delta était de 101339 ms. En d'autres termes, j'ai eu plus de 10 secondes d'attente par seconde rien que pour les tâches système.