SQL Server 如何處理緩衝區記憶體中空間不足的查詢的數據?
我的問題是 SQL Server 如何處理需要將更多數據量拉入緩衝區記憶體而不是可用空間的查詢?該查詢將包含多個連接,因此磁碟上不存在這種格式的結果集,它需要編譯結果。但即使在編譯之後,它仍然需要比緩衝區記憶體中的可用空間更多的空間。
我舉個例子。假設您有一個總共有 6GB 可用緩衝區記憶體空間的 SQL Server 實例。我執行一個讀取 7GB 數據的多個連接查詢,SQL Server 如何響應這個請求?它是否將數據臨時儲存在 tempdb 中?它失敗了嗎?它是否只從磁碟讀取數據並一次編譯段?
此外,如果我試圖返回 7GB 的總數據會發生什麼,這會改變 SQL Server 處理它的方式嗎?
我已經知道解決這個問題的幾種方法,我只是好奇 SQL Server 在按規定執行時如何在內部處理這個請求。
另外,我確信這些資訊存在於某個地方,但我一直未能找到它。
根據需要將頁面讀入記憶體,如果沒有可用的可用記憶體,則將最舊的未修改頁面替換為傳入頁面。
這意味著,如果您執行的查詢需要的數據多於記憶體,那麼許多頁面在記憶體中的壽命將非常短,從而導致大量 I/O。
您可以通過查看 Windows 性能監視器中的“頁面預期壽命”計數器來查看此效果。查看https://sqlperformance.com/2014/10/sql-performance/knee-jerk-page-life-expectancy以了解有關該計數器的一些重要資訊。
在評論中,您特別詢問了當查詢結果大於可用緩衝區空間時會發生什麼。舉個最簡單的例子,
select * from some_very_big_table;
假設表是 32GB,max server memory (MB)
配置為 24GB。所有 32GB 的表數據將一次讀入頁緩衝區中的頁,鎖存,格式化為網路數據包,並通過網路發送。這是逐頁發生的;您可以同時執行 300 個這樣的查詢,並且假設沒有發生阻塞,每個查詢的數據將被讀入頁面緩衝區空間,一次一個頁面,並以客戶端最快的速度放入網路中請求並使用數據。一旦每個頁面的所有數據都發送到網路上,該頁面就會解鎖,並且會很快被磁碟中的其他頁面替換。在更複雜的查詢的情況下,例如聚合多個表的結果,頁面將完全按照查詢處理器的要求被拉入記憶體。如果查詢處理器需要臨時工作空間來計算結果,它會在編譯查詢計劃時預先知道,並向SQLOS請求工作空間(記憶體) 。SQLOS 將在某個時候(假設它沒有超時)將該記憶體授予查詢處理器,此時查詢處理將恢復。如果查詢處理器在估計從 SQLOS 請求多少記憶體時出錯,它可能需要執行“溢出到磁碟”操作,其中數據以中間形式臨時寫入 tempdb。已寫入 tempdb 的頁面在寫入 tempdb 後將被解鎖,以便為其他頁面讀入記憶體騰出空間。最終,查詢過程將返回儲存在 tempdb 中的數據,使用鎖存將其分頁到緩衝區中標記為空閒的頁面中。
毫無疑問,我在上面的總結中遺漏了很多非常技術性的細節,但我認為這抓住了 SQL Server 如何處理超出記憶體容量的數據的本質。