合 MSSQL中的等待事件SOS_SCHEDULER_YIELD说明
Tags: MSSQLSQL Server等待事件书签查找SOS_SCHEDULER_YIELD
简介
SOS_SCHEDULER_YIELD等待类型是一个任务自愿放弃当前的资源占用,让给其他任务使用。 这个等待类型与CPU有直接关系,与内存也有间接关系,与CPU有关系是因为在sql server里是通过任务调度SCHEDULER来关联CPU。 通过SCHEDULER下的Worker线程来处理SQL任务。为什么跟内存有关系呢,是因为获取的资源需要内存来承载。
Yelding的发生:是指SCHEDULER上运行的Worker都是非抢占式的, 在 SCHEDULER上Worker由于资源等待,让出当前Worker给其它Worker就叫Yielding。 关于SCHEDULER_YIELD产生的原理查看 sqlserver 任务调度与CPU。SOS_SCHEDULER_YIELD 等待的情况可以了解到:
(1)CPU有压力
(2) SQL Server CPU scheduler 使用得当处理就会效率高。
sql server 调度器是非抢占式调度,也就是说是依靠查询自动放弃cpu,但是windows是抢占式,也就是说一定时间之后,windows 会直接从cpu上删除任务。
当查询自动放弃cpu,并且等待恢复执行,这个等待就叫做SOS_SCHEDULER_YIELD,如果这个值很小那么就说明,花费在等待cpu上,而不是等待其他资源上。
如果sys.dm_exec_requests或者 sys.dm_os_waiting_tasks 的SOS_SCHEDULER_YIELD的等待值偏高,那么说明有cpu密集型查询,需要优化sql或者增加cpu。
SQL Server 大部分时间都以非抢占模式运行,这意味着线程是协作的,并且可以通过让出自身来给其他线程运行。当任何线程为另一个线程让出自己占有的 Scheduler 时,它就会创建此等待类型。因此,如果线程过多,也间接表明CPU有压力。
调度程序中的线程为以下三种状态之一:
- RUNNING:线程正在处理器上运行,每个处理器同时只能有一个线程处于活动状态。
- SUSPENDED:对不可用资源的线程将移至等待列表中,直到资源可用(等待资源)。
- RUNNABLE:具有可用资源的线程,但被移至可运行队列,等待CPU变得可用(等待信号)。
不过,等待类型 SOS_SCHEDULER_YIELD 不涉及 SUSPENDED。
上图中,SPID=53在4毫秒内未执行完成,其让出 Scheduler 并进入Runnable 队列中,此时注册为SOS_SCHEDULER_YIELD 等待类型,不会发生资源等待(SUSPENDED)。这时候,SPID=58 则进入 Scheduler 中并执行处于 Running状态。
"SOS_SCHEDULER_YIELD" 是 SQL Server 中的一种等待类型,通常表示正在等待 CPU 资源的线程。如果在 SQL Server 实例中存在大量的 SOS_SCHEDULER_YIELD 等待,这可能意味着 SQL Server 实例正在遇到性能问题,其中 CPU 资源可能成为瓶颈。
以下是一些可能的原因以及相应的解决方法,以减少 SOS_SCHEDULER_YIELD 等待:
- CPU 资源不足:如果服务器的 CPU 资源不足,SQL Server 将不得不等待处理器时间片。这可能是硬件配置不足的问题。解决方法包括升级硬件、增加 CPU 核心数或考虑分散负载到多个服务器。
- 查询性能问题:某些查询可能会消耗大量的 CPU 资源,导致其他查询等待 CPU 时间片。通过优化查询、创建合适的索引以及使用适当的查询计划来改善查询性能。
- 并发连接数过多:如果 SQL Server 实例上有太多的并发连接,这可能导致 CPU 资源过度使用。考虑限制连接池大小或增加 CPU 资源。
- 过度并行查询:并行查询可以导致大量的线程等待 CPU 时间片。可以考虑通过调整最大并行度设置来限制并行查询的数量。
- 外部资源竞争:如果 SQL Server 依赖于外部资源(例如磁盘、网络、其他服务),这些资源的竞争也可能导致 CPU 等待。优化外部资源访问以减少等待。
- 缓存压力:如果 SQL Server 缓存不足,它可能需要更频繁地访问磁盘,从而增加 CPU 使用率。确保 SQL Server 有足够的内存来存储查询计划和数据缓存。
- 版本升级或修补程序:有时,SOS_SCHEDULER_YIELD 等待问题可能会由 SQL Server 的特定版本或修补程序引起。考虑升级 SQL Server 或应用相关的修补程序来解决问题。
为了更准确地诊断和解决 SOS_SCHEDULER_YIELD 问题,您可能需要使用 SQL Server 监控工具,如性能监视器和查询执行计划来分析性能问题的具体原因。同时,确保您的 SQL Server 实例和硬件配置满足您的工作负载需求,以防止性能问题的出现。
以并发任务为例:
1 2 3 4 | SELECT * FROM Sales.SalesOrderDetail A INNER JOIN Production.Product B ON A.ProductID = B.ProductID ORDER BY B.Name |
这两张表都使用了并发线程,我们设置的最大并发度为2,只能使用2个CPU处理(这里我们不考虑等待类型CXPACKET的情况)。我们假定,此刻数据库引擎正在扫描表获取数据,在4个线程中,也只能有2个线程处于Running状态。同一个CPU中,只能有一个线程正在 Running,如果4毫秒内未处理完,该线程则放入Runnable 队列(出现 SOS_SCHEDULER_YIELD 等待),让其他线程使用CPU。如此反复切换,即为CPU的上下文切换,CPU使用率也将升高。
上面的并发只是同一个连接请求发生的,如果有更多的用户连接请求呢?大家是不是就可能分配到同一个CPU了,CPU处理的任务越多,上下文切换也会越频繁,数据也重复地加载到CPU缓存中。而上下文切换协调各个线程的运行,保证能相对民主地执行用户的请求。
从实例级别来查看等待数
1 2 3 4 5 6 7 8 | select wait_type, waiting_tasks_count, wait_time_ms , max_wait_time_ms, signal_wait_time_ms from sys.dm_os_wait_stats where wait_type like 'SOS_SCHEDULER_YIELD%' order by wait_type |
查询如下图所示:
这个等待类型排名第二,从请求的次数来说有69367060次,也就是说该线程用完了4ms的时间片,主动放弃cpu。如果没有大量的runnable队列或者大量的signal wait,证明不一定是cpu问题。因为这两个指标是cpu压力的一个体现。需要检查执行计划中是否存在大量扫描操作。
通过dmv scheaduler的描述查看cpu压力
1 2 3 | 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 |
如下图所示:
如果你注意到runnable_tasks_count计数有两位数,持续很长时间(一段时间内),你就会知道CPU压力。两位数字通常被认为是一件坏事 无法应对当前负荷。另外可以通过性能监视器%Processor Time 来查看CPU的状况。
通过案例实时查看sql语句级的资源等待
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | SELECT * FROM sys.dm_exec_requests WHERE wait_type LIKE 'SOS_SCHEDULER_YIELD%' ; -- 或查找资源等待的 SELECT session_id, status, blocking_session_id , wait_type, wait_time, wait_resource , transaction_id FROM sys.dm_exec_requests WHERE status = N'suspended'; |
如下图所示 运行sys.dm_exec_requests 表,由于字段多截取了三断。会话202的sql 语句上一次 等待类型是SOS_SCHEDULER_YIELD。之所以会出现YIELD,是因为SCHEDULER下的Worker已经发起了task 命令,但由于资源等待 如锁或者磁盘输入/输出等,Worker又是非抢占式,所以让出了当前的Worker。