在今天的文章里我想詳細(xì)談下SQL Server里的統(tǒng)計(jì)等待(Wait Statistics),還有她們?nèi)绾螏椭懔⒓礊槭裁茨愕腟QL Server當(dāng)前很慢。一提到性能調(diào)優(yōu),對我來說統(tǒng)計(jì)等待是SQL Server了最重要的概念。
查詢?yōu)槭裁吹却?p>在SQL Server里每次你執(zhí)行1個查詢,查詢總需要等待。什么?查詢總需要等待?是的,你沒有看錯:但給你執(zhí)行1個查詢時(shí),查詢總需要等待。為什么查詢需要等待的原因是SQL Server通過所謂的等待統(tǒng)計(jì)(Wait Statistics)來跟蹤的。在我進(jìn)入等待統(tǒng)計(jì)(Wait Statistics)細(xì)節(jié)內(nèi)容前,我想談下SQL Server里查詢總需要等待的原因。在SQL Server里查詢發(fā)生等待有2個原因:我們來詳細(xì)看下這2類等待。當(dāng)你等待外部資源時(shí)會發(fā)生資源等待(Resource Wait)。這里我想你一些例子。每次一個查詢從緩存池請求1個頁時(shí),如果這個頁沒被緩存的話,緩存區(qū)管理器需要到你的存儲進(jìn)行異步I/O操作,從你的物理存儲讀取頁到緩存池。而且訪問物理存儲會非常慢。由于這個原因SQL Server會拿掉你查詢的CPU周期,查詢只會等待直到異步I/O操作完成(同事其它查詢可以更有效的使用CPU資源)。最后你的查詢繼續(xù)它的執(zhí)行。
當(dāng)你需要獲取鎖時(shí)也會發(fā)生同樣的事情——當(dāng)你想要讀或修改數(shù)據(jù)時(shí)。當(dāng)其它人已經(jīng)獲得了不兼容的鎖,你的查詢需要去等待直到鎖可以獲得。同時(shí)SQL Server會再次拿掉你的CPU周期,查詢需要去等待直到其它查詢的不兼容鎖釋放掉,這樣的話查詢本身可以獲得請求的鎖。
除資源等待外,SQL Server查詢還會因SQLOS(SQL Server操作系統(tǒng)(OS))內(nèi)部實(shí)現(xiàn)的協(xié)同調(diào)度(Cooperative Scheduling)而等待。SQL Server繞過Windows系統(tǒng)的搶占式調(diào)度(Cooperative Scheduling),調(diào)度它的線程本身。因?yàn)檫@樣的設(shè)計(jì)SQL Server會更容易擴(kuò)展,并為你提供更好的吞吐量。當(dāng)1個查詢在CPU上積極運(yùn)行時(shí),SQL Server本身就可以決定,當(dāng)1個查詢從CPU上拿掉時(shí),SQL Server也可以決定,這樣的話另1個查詢可以在那個CPU上活躍繼續(xù)它的查詢執(zhí)行。由于這個原因,一旦查詢溢出所謂的量(Quantum),SQL Server就會把你的查詢從CPU上拿掉。
量定義了查詢在CPU上可以活躍花費(fèi)的時(shí)間片(time slice)。在SQL Server里這個時(shí)間片是4毫秒長。這就是說一旦查詢完成它的工作超出4毫秒,SQL Server就會把你的查詢從CPU上拿掉。因此在SQL Server里查詢總是要等待。如果沒有資源等待,溢出量就會踢入,查詢會在CPU上睡著(going off)。你的查詢總會等待!
查詢生命周期我們我們知道了在SQL Server里查詢總需要等待。我們來進(jìn)一步看下它。當(dāng)你執(zhí)行1個查詢,這個查詢會進(jìn)入3個不同的狀態(tài),如下圖中所示:
我們來詳細(xì)說下這3個狀態(tài)。只要你的查詢在你的CPU上積極運(yùn)行,這個查詢是在RUNNING狀態(tài)。RUNNING狀態(tài)意味著你的查詢當(dāng)前正進(jìn)行一些工作。進(jìn)入這個狀態(tài)一直是你的首要目標(biāo)。當(dāng)SQL Server把你的查詢從CPU上拿掉時(shí),然后這個查詢移入了SUSPENDED狀態(tài)。查詢只要SUSPENDED狀態(tài)需要都會等待,直到請求的資源可用(回想下從你物理存儲讀取的頁,或者不能立即獲得的不兼容鎖)。
當(dāng)請求的資源可用時(shí),然后SQL Server把你的查詢移入RUNNABLE狀態(tài)。RUNNABLE狀態(tài)意味著你的查詢準(zhǔn)備好了繼續(xù)執(zhí)行,但它需要另外必需的東西:在它上面運(yùn)行的CPU。當(dāng)現(xiàn)在沒有可用的CPU時(shí)(因?yàn)槠渌樵儺?dāng)前在RUNNING狀態(tài)),查詢需要在RUNNABLE狀態(tài)花費(fèi)一些時(shí)間。 最后當(dāng)CPU變成可用時(shí),查詢移入RUNNING狀態(tài),然后一切輪回繼續(xù)。一個簡單的查詢在執(zhí)行期間,可以運(yùn)行上幾百次,甚至幾千次的查詢生命周期(query life cycle)。
分析等待統(tǒng)計(jì)(Wait Statistics)所有這些狀態(tài)事務(wù)被SQL Server跟蹤,并通過等待統(tǒng)計(jì)反饋給我們。SQL Server通過DMVsys.dm_os_wait_stats 來披露這些等待統(tǒng)計(jì)(Wait Statistics)。從這個DMV返回的每條記錄都是SQL Server里的1個等待原因。在SQL Server 2014里你共有771個不同的為什么查詢會等待的原因。什么?771個不同原因?跟我開玩笑吧?那是很多的!沒錯!但一般來說你只需要處理一些特定的等待原因,因?yàn)槲覀兠總€人幾乎都處理SQL Server里同樣的性能問題:
當(dāng)在面前有一個運(yùn)行慢的SQL Server,第一步我總看下等待統(tǒng)計(jì)里的詳細(xì)信息,因?yàn)樗鼈兏嬖V我為什么SQL Server里查詢在等待。但SQL Server里的等待統(tǒng)計(jì)只是個癥狀,不是問題根源本身!或許SQL Server通過等待統(tǒng)計(jì)告訴你在過去有一些因阻塞情形的等待。但可能是不是你有一個不好的索引設(shè)計(jì),缺失了一個非常重要的非聚集索引導(dǎo)致了阻塞情形?有了額外的非聚集索引你提供SQL Server額外的數(shù)據(jù)訪問路徑,是否你的阻塞情形就可以輕松解決?這只是癥狀并非根源的1個例子(很多中的)。
小結(jié)在這個文章里我給你概況介紹了在SQL Server里為什么查詢會等待,還有這些等待如何通過等待統(tǒng)計(jì)來跟蹤。等待統(tǒng)計(jì)里最重要的事情是SQL Server里它只告訴你癥狀,并不是問題根源。作為故障排除人,你的工作是讀和理解統(tǒng)計(jì)等待,最后挖出你SQL Server里更多的信息來找出潛在的問題根源。
感謝關(guān)注!
新聞熱點(diǎn)
疑難解答
圖片精選