???? 在SQL Server的世界中,SQL Server在Windows之上有一套自己的任務調度和資源分配系統,這使得SQL Server作為Windows的一個進程,卻可以處理大量的并發,這些任務調度和資源分配非常像一個操作系統,因此SQL Server在Windows之上,有一層被稱為SQL OS的系統。
??? 類似Windows進程之間的任務調度,SQL Server OS也有一套自己的調度方案,在早期的SQL Server曾經使用Windows自帶的進程調度系統,但由于SQL Server是一個處理高并發的進程,因此Windows調度造成的線程切換(Context Switch)會帶來很多的資源浪費,并且Windows調度是搶占式調度,這對于SQL Server來說非常不利,因此SQL Server OS通過非搶占式調度算法來調度進程,除非線程自己釋放資源,SQL Server不會強制剝奪資源(當然了,一些極端情況比如死鎖,或是檢查scheduler時發現不利問題,會記錄到日志,但依然不會搶占資源),這也使得開發人員對T-SQL語句需要小心,當然了這是題外話了。
??? 在了解了SQL Server基本的調度算法后,再讓我們通過一個圖來了解一下簡單的SQL Server中線程的幾種狀態(這類線程對Windows來說是線程,對SQL Server來說是進程,這也是為什么查詢這些線程的時候用的是Sysprocess),如圖1所示。
???
??? 圖1.SQL Server OS的簡單算法
??? 如果你了解操作系統的調度算法的話,你會發現這里和操作系統的形式一樣,當線程得到等待的資源并獲得CPU時,就會是運行狀態,而當獲得資源沒有CPU時,就會是Runnable狀態,或是當線程所需的資源沒有到位時,就會是阻塞狀態。
??? 因此,多個CPU可以有多個線程在Running狀態。
??? 另外在SQL Server中,每創建一個新表時,都會為表分配存儲頁面,相應的,SQL Server也需要修改GAM,SGAM和FPS頁。對于修改這些頁來說,SQL Server需要在修改的時候加上一個輕量級的鎖,這也就是所謂的閂鎖(Latch)。當多個線程同時需要修改GAM,SGAM,FPS頁時,閂鎖會造成阻塞。對于用戶數據庫來說,不可能一直存在DDL操作,但對于Tempdb來說,會經常進行建表和刪表,因此對于GAM,SGAM以及FPS頁都會經常修改,如果Tempdb只有一個文件而CPU存在多核的時候,多個同時運行的任務有可能爭搶GAM,SGAM,FPS頁的修改權,因此造成阻塞,這對性能是非常不利的,而按照CPU個數將TempDB的文件分為多份,則會存在多個GAM,SGAM,FPS頁。多個Running的線程會按照每個文件的大小平均分布到不同的文件中,因此解決了爭用問題。
??? 另外,值得注意的是,對于TempDB的最佳做法是一開始就為每一個文件分配足夠大的值。并且每個文件大小相等,這就避免了某個文件增長導致的文件大小不一,而SQL Server對于文件的使用比率是按照文件大小,如果文件大小不一樣,就會造成熱點文件,從而有可能造成閂鎖爭用。