2010-01-11 89 views
4

當sql服務器正在同時接收兩個查詢(SELECT * from the_Same_Table)時,並且如果你有一個具有多個處理器的服務器,sql server是否可以同時檢索數據?SQL服務器併發訪問

我想了解如果在0.01秒內完成的廉價選擇語句和1000個用戶在同一時間精確運行相同的查詢會發生什麼情況。我認爲如果服務器有四個處理器會發生什麼情況,那麼SQL服務器將在.01秒內爲前四個服務器提供服務,並在0.02秒內爲後面的四個用戶提供額外服務。

這甚至接近實際發生的事情嗎?

我想我會嘗試使用某種代碼和記錄器來測試,或者有可靠的測試工具來做到這一點。

感謝

回答

14

進入SQL Server的每個批次(請求)都會創建一個任務。任務計劃執行並由工作人員提取。工人與線程非常相似。一個任務與一個工作人員在一起,直到它完成,然後釋放工人來完成另一個任務。系統中的工作人員數量有限,由sp_configure 'max worker threads'配置。至少有256名工人,其中約35人是系統工人。一名工作人員需要一個調度程序來運行,並且每個CPU核心都有一個調度程序。工作人員合作共享調度程序。

某些任務產生了子任務,就像並行查詢一樣。這些任務也排隊等待執行並需要工作人員完成。產生子任務的任務不能完成,直到它產生的所有任務完成。

還有一些用戶操作驅動的系統任務,如登錄握手。當客戶端打開一個新的連接時,握手和登錄認證/授權由一個任務完成,該任務需要一個工作人員。

當1000個請求到達服務器時,會創建1000個任務並排隊等待執行。免費工作人員拿起任務並開始執行任務。當他們完成一項任務時,他們選擇下一個任務,直到完成1000個請求創建的所有任務。

,顯示發生了什麼事情的動態管理視圖是:

這些細節SQL Server Batch or Task SchedulingSlava's blog描述。

此外,一旦任務正在執行,請求將被編譯。編譯將首先查找內存中的請求文本,並搜索具有相同計劃的請求的現有編譯計劃。您可以閱讀我對Dynamically created SQL vs Parameters in SQL Server的回覆,以獲取更詳細的信息,瞭解這種情況。另見Execution Plan Caching and Reuse。一旦創建了一個計劃,它就會啓動執行。像SELECT ... FROM table這樣的查詢將創建一個簡單的計劃,只有幾個操作員基本上獲取每行,並將其放入TDS流返回給客戶端。查詢計劃是一個操作符樹,查詢總是通過循環查詢樹的根,直到根返回EOF來執行。樹中的查詢操作符越來越具體,直到底層操作符將成爲對所選訪問路徑(優化器爲滿足查詢而選擇的索引或堆)的物理訪問。見SQL Statement Processing。索引訪問將始終從緩衝池請求數據,永遠不會從磁盤請求。當緩衝池沒有緩存所請求的頁面時,會在頁面上放置PAGEIOLATCH,並將讀取頁面的請求提交給IO子系統。隨後對同一頁面的請求將等待此IO完成,並且一旦頁面位於緩衝池中,所有其他需要此頁面的查詢都將從緩衝池中進行查詢。當緩衝池需要空閒頁面時,未使用的頁面會被清除,但是如果系統具有足夠的RAM,那麼一旦加載頁面,頁面就不會被驅逐。索引和堆掃描操作將請求預讀,預計頁面鏈接鏈中當前頁面之前的頁面將被請求。預讀受限於索引連續片段,這是索引碎片進入畫面時的情況,因爲它減少了預讀請求的大小,請參閱Understanding Pages and Extents

查詢執行的另一個維度是行的邏輯鎖定。爲了保持穩定性,讀取操作可能會在讀取的行上放置行鎖定或範圍鎖定(取決於隔離模型),以防止查詢遍歷掃描時進行更新。在SNAPSHOT隔離級別下,查詢根本不會請求鎖定,而是使用版本標記來服務從版本存儲請求的數據(請參閱SQL Server 2005 Row Versioning-Based Transaction Isolation)。在READ UNCOMMITED隔離下(或使用nolock提示時),查詢不會請求讀取行的鎖定,但如果發生concurent更新(讀取未定義的行,可能讀取同一行兩次或存在的行,則讀取不一致可能根本不讀)。

+0

+1 Remus記得比我更好,你一定是在看Remus的大師認證? – Andrew 2010-01-11 17:16:48

+0

@Andrew:我沒有那麼多的現金來燃燒:) – 2010-01-11 17:36:02

+0

知道這種感覺 - 我會有酒店+航班來支付。 – Andrew 2010-01-11 17:37:40

2

不,你的順序處理的假設是不正確的,這個話題變得非常複雜和深刻的 - 試圖讓我知道它很簡單:

每個查詢分配一個線程和調度器使用協作式調度,而不是先發制人,所以每個線程都可以在被調度器強制執行之前放棄時間分配(量子)。 每個查詢將不得不從緩衝池中請求數據,這可能意味着等待IO /網絡等,因此它們將等待狀態併產生處理時間量。

當進程不再等待資源時,可以重新輸入可用於處理的線程列表,然後再獲取另一個時間量來處理請求。

實際上,您的請求並行運行,但您無法確定性地預測請求的完成順序。

爲了深入瞭解這一點,我正在考慮SQL 2008內部書籍Kalen Delaney(Adam Mechanic,Kimberley Tripp,Paul Randal)是一個很好的起點,或者Ken的舊版SQL Server 2000架構書亨德森,這也是非常低的水平。

我必須回頭參考課程筆記來記住確切的過程 - 它會問到 - 因爲你不能直接影響這個過程,你爲什麼要問?

+0

驗證會使我緩存便宜數據的原因。基於這個線程,我不會緩存與一個客戶相關的廉價數據,我會緩存所有客戶可能需要的所有數據,因爲在avg_case中,當用戶數量增加時,吞吐量將會減少。你同意嗎? 謝謝 – Costa 2010-01-11 17:23:34

+0

您必須指SQL Server外部緩存,因爲它將爲您處理過程/數據緩存。如果數據的請求頻率足夠高,它將位於SQL Server數據高速緩存中,或者可能位於IO子系統高速緩存(例如,SAN高速緩存)中。 要小心,您沒有執行過早的優化,沒有實際的檢測數據來表明您確實存在性能問題 - 可以預期最壞的情況,但您無法知道某些定製編碼緩存是否會比你正在取代什麼,因爲你沒有時間去比較。 – Andrew 2010-01-11 17:35:37

0

Sql服務器針對併發多重讀取進行了優化。唯一可能遇到死鎖的情況是,如果您在嘗試訪問的同一張桌面上發生大量更新操作。但是,如果是這種情況,您可以使用nolock或甚至將事務隔離級別設置爲READ UNCOMMITTED

現在關於你的線程問題。 SQL Server使用稱爲纖維的東西,它就像一個子線程。所以你不一定會看到你期望在多處理器環境中看到的相同的處理器線程擴展。儘管SQL服務器可以訪問一定數量的線程,但也可以使用最大數量的光纖。這就是爲什麼你可以讓1000個客戶端在同一個小盒子上同時訪問同一臺服務器。

如果你真的真的想進入線程/光纖調度,你將需要去找一個好的SQL Server的堅果和螺絲的人,真的真的得到它,因爲它很複雜。

只要意識到sql服務器已經爲此進行了優化,並且您不需要以任何方式進行單元測試,因爲已經用工具驗證過了,您可能無法重新創建該工具。