SOS_SCHEDULER_YIELD очень интересный вид ожиданий и я его часто вижу.
ИЗ Book On-Line:
Occurs when a task voluntarily yields the scheduler for other tasks to execute. During this wait the task is waiting for its quantum to be renewed.
Объяснение:
SQL Server имеет множество потоков и основной девиз SQL Server — он не даёт «голодать» «runnable» потокам. В SQL Server постоянно появляются новые потоки, которые готовы к запуску (runnable). Управление потоками происходит на уровне SQL Server, а не на уровне операционной системы. SQL Server работает в состоянии non-preemptive большую часть времени, это означает, что потоки могут время от времени позволять выполняться другим потокам, вместо себя. Когда поток, жертвует себя другому потоку, это создаёт данный вид ожиданий. Если так поступают многие потоки, то это значит, что есть большая нагрузка на CPU.
Вы можете посмотреть, сколько runnable сейчас в вашей системе:
SELECT scheduler_id, current_tasks_count, runnable_tasks_count, work_queue_count, pending_disk_io_count FROM sys.dm_os_schedulers WHERE scheduler_id < 255 GO
Если вы будете наблюдать в столбце runnable_tasks_count двузначное число долгое время, то это значит, что у вас большая нагрузка на процессор.
Уменьшение SOS_SCHEDULER_YIELD ожиданий:
Как мы обсудили выше, данный вид ожиданий оказывает нагрузку на процессор. Увеличение количества процессоров, это лёгкий способ избавиться от SOS_SCHEDULER_YIELD, однако это не всегда можно сделать. Поэтому есть другие способы решить эту задачу. Вот код, который вернёт наиболее дорогие запросы по процессору из кэша:
Обратите внимание, что запросы, план которых не остался в кэше, не будут возвращены.
SELECT SUBSTRING(qt.TEXT, (qs.statement_start_offset/2)+1, ((CASE qs.statement_end_offset WHEN -1 THEN DATALENGTH(qt.TEXT) ELSE qs.statement_end_offset END - qs.statement_start_offset)/2)+1), qs.execution_count, qs.total_logical_reads, qs.last_logical_reads, qs.total_logical_writes, qs.last_logical_writes, qs.total_worker_time, qs.last_worker_time, qs.total_elapsed_time/1000000 total_elapsed_time_in_S, qs.last_elapsed_time/1000000 last_elapsed_time_in_S, qs.last_execution_time, qp.query_plan FROM sys.dm_exec_query_stats qs CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) qt CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp ORDER BY qs.total_worker_time DESC -- CPU time
Так вы найдёте самые дорогие запросы по процессору и сможете улучшить их.
Так же обратите внимание на total_worker_time, если этот показатель так же высок, то нагрузка на процессор чрезвычайно высокая.
Перестройка индексов, так же сильно нагружает процессор, но это необходимая операция, особенно на OLTP системах.
Заметка: Представленная тут информация является только моим опытом. Я настраиваю, чтобы вы читали Books On-Line. Все мои обсуждения ожиданий здесь носят общий характер и изменяются от системы к системе. Я рекомендую сначала тестировать всё на сервере разработки, прежде чем применять это на рабочем сервере.
Автор: Pinal Dave
*** *** *** *** *** *** *** *** *** *** *** ***
Полезные Скрипты
Рубрика Проверь себя
Ссылка на наш канал YouTube