主頁 > 知識(shí)庫 > SqlServer應(yīng)用之sys.dm_os_waiting_tasks 引發(fā)的疑問(中)

SqlServer應(yīng)用之sys.dm_os_waiting_tasks 引發(fā)的疑問(中)

熱門標(biāo)簽:AI電銷 百度競(jìng)價(jià)排名 地方門戶網(wǎng)站 網(wǎng)站排名優(yōu)化 Linux服務(wù)器 呼叫中心市場(chǎng)需求 鐵路電話系統(tǒng) 服務(wù)外包

 通過上篇文章給大家介紹了SqlServer應(yīng)用之sys.dm_os_waiting_tasks 引發(fā)的疑問(上) ,說了一下sys.dm_exec_requests 和 sys.dm_os_waiting_tasks 在獲取并行等待的時(shí)候得不同結(jié)果,這一篇我們談?wù)撓挛业牡诙€(gè)疑問:為什么一個(gè)并行計(jì)劃(4線程)卻一下出現(xiàn)了那么多等待,SQL的并行到底是怎么執(zhí)行的!?。?!

    先貼以下上篇sys.dm_os_waiting_tasks 的結(jié)果圖:

     我們分析一下這個(gè)結(jié)果的task_address 可以看出去掉重復(fù)其實(shí)只有9個(gè),也就是說一個(gè)并行(4線程,配置不同,情況也不同)會(huì)有9個(gè)task。 又是線程,又是task ,還有worker,schedulers 這些都是什么? 這個(gè)有必要先說一下,因?yàn)檫@篇博客前我也是亂亂的。

 scheduler

對(duì)于每個(gè)邏輯CPU,SQLSERVER會(huì)有一個(gè)scheduler與之對(duì)應(yīng),在SQL層面上代表CPU對(duì)象,只有拿到scheduler所有權(quán)的任務(wù)worker才能在這個(gè)邏輯CPU上運(yùn)行

所謂邏輯CPU,就是SQLSERVER從Windows層面上看到的CPU數(shù)目,如果是一個(gè)雙核的CPU,那么一個(gè)物理CPU在SQL看來就是兩個(gè)邏輯CPU。如果系統(tǒng)還使用了

超線程hyper-threaded ,那對(duì)SQLSERVER來講就是4個(gè)邏輯CPU

規(guī)則: 每個(gè)scheduler上的最大worker數(shù)目等于SQLSERVER的最大線程數(shù)除以scheduler的數(shù)目 ,在同一個(gè)時(shí)間點(diǎn),只能有一個(gè)擁有scheduler的worker處于運(yùn)行狀態(tài),其他worker都必須處于等待狀態(tài)。這樣能降低每個(gè)邏輯CPU上的處于正在運(yùn)行狀態(tài)的線程數(shù)目,降低context switch,提供可擴(kuò)展性scheduler是SQLSERVER的一個(gè)邏輯概念,他不與物理CPU相綁定。也就是說,一個(gè)scheduler可以被Windows安排一會(huì)兒在這個(gè)CPU上,一會(huì)兒在那個(gè)CPU上。

 但是,如果在sp_configure里設(shè)置了CPU affinity mask,那么scheduler就會(huì)固定在某個(gè)特定的CPU上

worker

每個(gè)worker跟一個(gè)線程(或纖程fiber)相對(duì)應(yīng),是SQLSERVER任務(wù)的執(zhí)行單位。SQLSERVER不直接調(diào)度線程/纖程,而是調(diào)度worker,使得SQLSERVER能夠控制

任務(wù)調(diào)度

規(guī)則: 每個(gè)worker會(huì)固定代表一個(gè)線程(或纖程),并且和一個(gè)scheduler相綁定。如果scheduler是固定在某個(gè)CPU上的(通過設(shè)置CPU affinity mask),那么worker也會(huì)固定在某個(gè)CPU上每個(gè)scheduler有worker的上限值,并且可以根據(jù)SQLSERVER工作負(fù)荷創(chuàng)建或釋放worker,每次worker都會(huì)去運(yùn)行一個(gè)完整的任務(wù)(task)。在任務(wù)做完之前不會(huì)退出,除非這個(gè)任務(wù)主動(dòng)進(jìn)入等待狀態(tài)。

scheduler只在有新任務(wù)要運(yùn)行,而當(dāng)前沒有空閑的worker的情況下,才會(huì)創(chuàng)建新的worker。

某個(gè)worker空閑超過15分鐘,scheduler可能會(huì)刪除這個(gè)worker,以及其對(duì)應(yīng)的線程。當(dāng)SQLSERVER遇到內(nèi)存壓力的時(shí),也會(huì)大量刪除處于空閑狀態(tài)的worker,以節(jié)省multi-page的內(nèi)存開銷各種CPU和SQLSERVER版本組合自動(dòng)配置的最大工作線程數(shù)CPU數(shù)                 32位計(jì)算機(jī)                        64位計(jì)算機(jī)
=4                     256                                  512
8                          288                                  576
16                        352                                  704
32                        480                                  960

task

在worker上運(yùn)行的最小任務(wù)單元。最簡(jiǎn)單的task就是一個(gè)簡(jiǎn)單batch。例如,客戶發(fā)過來下面的請(qǐng)求:

 SELECT @@SERVERNAME
 GO
 SELECT GETDATE()
 GO 

那么這兩個(gè)batch就分別是兩個(gè)task。SQLSERVER會(huì)先分配給第一個(gè)batch(select @@servername)一個(gè)worker,將結(jié)果返回給客戶端,再分配第二個(gè)batch

(select getdate())一個(gè)worker。這兩個(gè)worker可能是不同的worker,甚至在不同的scheduler上只要一個(gè)task開始運(yùn)行,他就不會(huì)從這個(gè)worker上被移出。例如,如果一個(gè)select語句被其他連接阻塞住,worker就不能繼續(xù)運(yùn)行,只能進(jìn)入等待狀態(tài)。但是這個(gè)select task 不會(huì)將這個(gè)worker釋放,讓他做其他任務(wù)。所以結(jié)果是這個(gè)worker所對(duì)應(yīng)的線程會(huì)進(jìn)入等待狀態(tài)

yielding

 SQLOS的任務(wù)調(diào)度算法的核心,就是所有在邏輯scheduler上運(yùn)行的worker都是非搶占式的 (non-preemptive)。worker始終在scheduler上運(yùn)行,直到他運(yùn)行結(jié)束,或者主動(dòng)將scheduler讓出給其他worker為止。這個(gè)“讓出”scheduler的動(dòng)作,我們叫yieding每個(gè)scheduler都會(huì)有一個(gè)runnable列表,所有等待CPU運(yùn)行的worker都會(huì)在這個(gè)列表里排隊(duì),以先進(jìn)先出的算法,等待SQL分配給他scheduler運(yùn)行SQLSERVER定義了很多yieding的規(guī)則,約束一個(gè)task在scheduler運(yùn)行的時(shí)間。如果task比較復(fù)雜,不能很快完成,會(huì)保證task在合適的時(shí)間點(diǎn)做yieding,不至于占用scheduler太多時(shí)間。

常見時(shí)間點(diǎn):

1、當(dāng)worker每次要去讀數(shù)據(jù)頁的時(shí)候,SQLSERVER會(huì)檢查這個(gè)worker已經(jīng)在scheduler上運(yùn)行了多久,如果已經(jīng)超過4ms,就做yielding

2、每做64KB的結(jié)果集排序,就會(huì)做一次yielding

3、在做語句編譯compile的過程中(這個(gè)過程比較占CPU資源),經(jīng)常會(huì)有yieding

4、如果客戶端不能及時(shí)把結(jié)果集取走,worker就會(huì)做yieding

5、一個(gè)batch里的每一句話做完,都會(huì)做一次yieding

正常來講,哪怕一個(gè)task要做很久,他使用的worker是會(huì)經(jīng)常做yieding的,不會(huì)長(zhǎng)時(shí)間占用CPU不放。如果在一個(gè)scheduler上同時(shí)有很多worker要運(yùn)行,SQLSERVER通過worker自動(dòng)yielding的方式調(diào)度并發(fā)運(yùn)行。這個(gè)比Windows用上下文切換context switch更有效

    另附一張手繪圖

    另外推薦一篇 SQL SERVER SQLOS的任務(wù)調(diào)度 微軟亞太的官方博客

    我們大概了解了一下SQL SERVER SQLOS的任務(wù)調(diào)度 我們回到我們的并行話題看一下這個(gè)并行執(zhí)行的調(diào)度情況: 


    一個(gè)并行處理分配給了9個(gè)task,同時(shí)也啟用了9個(gè)worker,由4個(gè)scheduler調(diào)度,每個(gè)scheduler分別由一個(gè)申請(qǐng)數(shù)據(jù),另一個(gè)等待。那么申請(qǐng)數(shù)據(jù)的是可以理解的,等待的是干什么的呢?個(gè)人理解和當(dāng)前的執(zhí)行計(jì)劃有關(guān),4個(gè)線程取得數(shù)據(jù)后要做匯總的操作SQL不會(huì)等待數(shù)據(jù)獲取以后再開啟線程接收,而是接收線程在獲取數(shù)據(jù)的時(shí)候等待。

     

 疑問得到解決了么?因?yàn)橐呀?jīng)標(biāo)記為中篇,可見還是有疑問呀?。。?!我們繼續(xù)下一篇吧....

您可能感興趣的文章:
  • SqlServer應(yīng)用之sys.dm_os_waiting_tasks 引發(fā)的疑問(上)
  • SQL Server 2016里的sys.dm_exec_input_buffer的問題

標(biāo)簽:黃山 衡水 銅川 仙桃 湖南 湘潭 蘭州 崇左

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《SqlServer應(yīng)用之sys.dm_os_waiting_tasks 引發(fā)的疑問(中)》,本文關(guān)鍵詞  ;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 收縮
    • 微信客服
    • 微信二維碼
    • 電話咨詢

    • 400-1100-266