記憶體管理結構指南

適用於:SQL ServerAzure SQL DatabaseAzure SQL 受控執行個體Azure Synapse AnalyticsAnalytics Platform System (PDW)

Windows 虛擬記憶體管理員

此位址空間的認可區域是由「Windows 虛擬記憶體管理員 (VMM)」對應到可用的實體記憶體。

如需有關不同作業系統所支援之實體記憶體數量的詳細資訊,請參閱 Windows 文件Windows 版本的記憶體限制

虛擬記憶體系統會允許超額認可實體記憶體,所以虛擬記憶體與實體記憶體的比率可超過 1:1。 因此,大型程式可在使用各種實體記憶體設定的電腦上執行。 然而,使用的虛擬記憶體若遠大於所有處理序的平均工作集組合,可能會導致效能降低。

SQL Server 記憶體結構

SQL Server 會視需要動態地取得和釋放記憶體。 管理員通常不必指定 SQL Server 要配置多少記憶體,但在部分環境中仍有該選項,需要指定記憶體數量。

所有資料庫軟體的主要設計目的之一,便是將磁碟 I/O 最小化,因為磁碟的讀取和寫入,是電腦上最需要用到大量資源的作業之一。 SQL Server 會在記憶體中建立緩衝集區,以保存從資料庫讀取的分頁。 SQL Server 的大部分程式碼,主要是用來最小化磁碟和緩衝集區之間實體讀取和寫入次數。 SQL Server 嘗試在兩個目標之間取得平衡:

  • 避免緩衝集區過大,造成整個系統的記憶體不足。
  • 最大化緩衝集區的大小以最小化資料庫檔案的實體 I/O。

在高負載系統中,部分需要大量記憶體執行的大量查詢,無法取得所需的最低記憶體,而在等候記憶體資源時發生逾時錯誤。 若要解決這個問題,請增加 查詢等候選項。 如果是平行查詢,請考慮減少 平行處理原則的最大程度選項

在記憶體負載極高的系統中,若在查詢計畫中使用合併聯結、排序與點陣圖的查詢,當查詢無法取得點陣圖所需的最低記憶體時,會卸除點陣圖。 這時會影響查詢效能,同時如果排序處理序無法順應記憶體調整,排序處理序可能增加 tempdb 資料庫中工作資料表的使用量,導致 tempdb 成長。 若要解決此問題,請新增實體記憶體,或調整查詢並使用不同且更快的查詢計畫。

常設 (虛擬) 記憶體

所有 SQL Server 版本都支援 64 位元平台的常設記憶體。 SQL Server 處理序可存取最高 x64 結構的作業系統虛擬位址空間 (SQL Server 標準版最高支援 128 GB)。 使用 IA64 結構時,上限為 7 TB (SQL Server 2012 (11.x) 和更新版本不支援 IA64)。 如需詳細資訊,請參閱 Windows 的記憶體限制

存取 Windows 延伸模組 (AWE) 記憶體

使用 AWE 所需的存取 Windows 延伸模組 (AWE) 與鎖定記憶體分頁 (LPIM) 權限後,在低虛擬記憶體條件下,您可以保留實體 RAM 中鎖定的大部分 SQL Server 處理序記憶體。 32 位元和 64 位元 AWE 配置都會發生此情況。 記憶體鎖定的原因是 AWE 記憶體不會通過透過 Windows 中的虛擬記憶體管理員,藉此控制記憶體分頁。 AWE 記憶體配置 API 需要鎖定記憶體分頁 (SeLockMemoryPrivilege) 權限,請參閱 AllocateUserPhysicalPages 說明。 因此,使用 AWE API 的主要優點是:如果系統有記憶體壓力,RAM 會保留大部分記憶體駐留。 如需如何允許 SQL Server 使用 AWE 的資訊,請參閱啟用鎖定記憶體分頁選項

如果已授與 LPIM,強烈建議您將最大伺服器記憶體 (MB) 設為特定值,而不保留 2,147,483,647 MB 的預設值。 如需詳細資訊,請參閱伺服器記憶體伺服器設定:手動設定選項鎖定記憶體分頁 (LPIM)

如果未啟用 LPIM,SQL Server 會切換至使用常設記憶體,且如果 OS 記憶體耗盡,就可能在錯誤記錄檔中回報錯誤 17890。 此錯誤類似下列範例:

A significant part of SQL Server process memory has been paged out. This may result in a performance degradation. Duration: #### seconds. Working set (KB): ####, committed (KB): ####, memory utilization: ##%.

從 SQL Server 2012 (11.x) 開始對記憶體管理進行的變更

在舊版 SQL Server 中,記憶體配置使用五種不同的機制:

  • 單頁配置器 (SPA),只包括SQL Server 處理序中低於或等於 8 KB 的記憶體配置。 [最大伺服器記憶體 (MB)] 與 [最小伺服器記憶體 (MB)] 設定選項決定了 SPA 可取用的實體記憶體上限。 緩衝集區同時是 SPA 的機制,以及單頁配置的最大取用者。
  • 多頁配置器 (MPA),適用於要求超過 8KB 的記憶體配置。
  • CLR 配置器,包括 SQL CLR 堆積,及其在 CLR 初始化期間所建立的全域配置。
  • SQL Server 處理序中執行緒堆疊的記憶體配置。
  • 直接 Windows 配置 (DWA) ,適用於直接向 Windows 提出的記憶體配置要求。 這些包括使用 Windows 堆積,以及載入至 SQL Server 處理序之模組所做的直接虛擬配置。 這類的記憶體配置要求範例,包括擴充預存程序 DLL 的配置、使用「自動」處理序 (sp_OA 呼叫) 所建立的物件,以及連結伺服器提供者的配置。

從 SQL Server 2012 (11.x) 開始,單頁配置、多頁配置和 CLR 配置全部合併為「任何大小」分頁配置器,並納入 [最大伺服器記憶體 (MB)] 與 [最小伺服器記憶體 (MB)] 設定選項控制的記憶體限制。 此變更針對經由 SQL Server 記憶體管理員的所有記憶體需求,提供更準確的調整大小功能。

重要

升級為 SQL Server 2012 (11.x) 和更新版本後,請仔細檢閱目前的 [最大伺服器記憶體 (MB)] 與 [最小伺服器記憶體 (MB)] 設定。 這是因為從 SQL Server 2012 (11.x) 開始納入這類設定,且記憶體配置比舊版占更多。 這些變更同時適用於 32 位元和 64 位元版本的 SQL Server 2012 (11.x) 與 SQL Server 2014 (12.x),以及 64 位元版本的 SQL Server 2016 (13.x) 和更新版本。

下表指出特定類型的記憶體配置是否受 [最大伺服器記憶體 (MB)] 與 [最小伺服器記憶體 (MB)] 設定選項的控制:

記憶體配置類型 SQL Server 2005 (9.x)、SQL Server 2008 (10.0.x) 和 SQL Server 2008 R2 (10.50.x) 從 SQL Server 2012 (11.x) 開始
單頁配置 是,已整合為「任何大小」分頁配置
多頁配置 是,已整合為「任何大小」分頁配置
CLR 配置
執行緒堆疊記憶體
Windows 直接配置 No

從 SQL Server 2012 (11.x) 開始,SQL Server 配置的記憶體可能超過 [最大伺服器記憶體 (MB)] 設定指定的值。 當 [總伺服器記憶體 (KB)] 值已經超過 [目標伺服器記憶體 (KB)] 設定 (由 [最大伺服器記憶體 (MB)] 指定) 時,即可能出現此行為。 如因記憶體分散,導致連續可用記憶體不足以符合多頁記憶體要求的需求 (大於 8 KB),SQL Server 仍可超額配置而不拒絕記憶體要求。

執行配置後,資源監視器背景工作會開始要求所有記憶體取用者釋出配置的記憶體,並嘗試讓 [總伺服器記憶體 (KB)] 值低於 [目標伺服器記憶體 (KB)] 規格。 因此,SQL Server 記憶體使用量可能暫時超過 [最大伺服器記憶體 (MB)] 設定。 在這個情況下,[總伺服器記憶體 (KB)] 效能計數器讀數會超過 [最大伺服器記憶體 (MB)]和 [目標伺服器記憶體 (KB)] 設定。

下列作業期間通常會觀察到此行為:

  • 大型資料行存放區索引查詢
  • 資料列存放區查詢的大型批次模式
  • 資料行存放區的重建/建置,這會使用大量的記憶體來執行雜湊與排序作業
  • 需要大型記憶體緩衝區的備份作業
  • 需要儲存大量輸入參數的追蹤作業

從 SQL Server 2012 (11.x) 開始對 memory_to_reserve 進行的變更

在舊版 SQL Server 中,SQL Server 記憶體管理員保留部分處理虛擬位址空間 (VAS),供多頁配置器 (MPA)CLR 配置器、SQL Server 處理序中執行緒堆疊的記憶體配置,及直接 Windows 配置 (DWA) 使用。 這部分的虛擬位址空間又稱為「假釋記憶體」(Mem-To-Leave) 或「非緩衝集區」區域。

為這些配置保留的虛擬位址空間會依 memory_to_reserve 設定選項而定。 SQL Server 使用的預設值是 256 MB。

因為「任何大小」分頁配置器也處理大於 8 KB 的配置,所以 memory_to_reserve 值不包含多頁配置。 除此變更之外,此設定選項的其餘項目皆維持原狀。

下表指出特定類型的記憶體配置是否屬於 SQL Server 處理序虛擬位址空間的 memory_to_reserve 區域:

記憶體配置類型 SQL Server 2005 (9.x)、SQL Server 2008 (10.0.x) 和 SQL Server 2008 R2 (10.50.x) 從 SQL Server 2012 (11.x) 開始
單頁配置 否,已整合為「任何大小」分頁配置
多頁配置 否,已整合為「任何大小」分頁配置
CLR 配置
執行緒堆疊記憶體
Windows 直接配置 Yes

動態記憶體管理

SQL Server 資料庫引擎的預設記憶體管理行為是以不造成系統發生記憶體短缺為前提,盡可能取得所需的記憶體。 SQL Server 資料庫引擎使用 Microsoft Windows 的記憶體通知 API 來達成這個目的。

動態使用記憶體時,SQL Server 會定期查詢系統,以判斷可用的記憶體數量。 維持這個可用記憶體數量可避免作業系統 (OS) 進行分頁。 如果可用記憶體較少,SQL Server 會將記憶體釋出至 OS。 如果可用記憶體較多,SQL Server 可能配置較多記憶體。 只有工作負載需要更多的記憶體時,SQL Server 才會增加記憶體;待用伺服器不會增加虛擬位址空間的大小。 如果您看到 SQL Server 使用動態記憶體管理時,工作管理員和效能監視器顯示可用記憶體穩定地減少。這是預設行為,而不是記憶體流失。

最大伺服器記憶體會控制 SQL Server 記憶體配置、編譯記憶體、所有快取 (包括緩衝集區)、查詢執行記憶體授與鎖定管理員記憶體,及 CLR1 記憶體 (前提是 sys.dm_os_memory_clerks 中找到任何記憶體 Clerk)。

1 從 SQL Server 2012 (11.x) 開始,CLR 記憶體是由 max_server_memory 配置管理。

以下查詢會傳回目前所配置之記憶體的相關資訊:

SELECT
  physical_memory_in_use_kb/1024 AS sql_physical_memory_in_use_MB,
    large_page_allocations_kb/1024 AS sql_large_page_allocations_MB,
    locked_page_allocations_kb/1024 AS sql_locked_page_allocations_MB,
    virtual_address_space_reserved_kb/1024 AS sql_VAS_reserved_MB,
    virtual_address_space_committed_kb/1024 AS sql_VAS_committed_MB,
    virtual_address_space_available_kb/1024 AS sql_VAS_available_MB,
    page_fault_count AS sql_page_fault_count,
    memory_utilization_percentage AS sql_memory_utilization_percentage,
    process_physical_memory_low AS sql_process_physical_memory_low,
    process_virtual_memory_low AS sql_process_virtual_memory_low
FROM sys.dm_os_process_memory;

堆疊大小

執行緒堆疊的記憶體 1、CLR 2、擴充處理序 .dll 檔案、分散式查詢所參考的 OLE DB 提供者、Transact-SQL 陳述式參考的自動化物件,及非 SQL Server DLL 配置的任何記憶體,皆最大伺服器記憶體 (MB) 控制。

1 請參閱文章「設定最大背景工作執行緒伺服器設定選項」,了解目前主機中,為指定數量之親和 CPU 而計算出的預設背景工作執行緒相關資訊。 SQL Server 堆疊大小如下:

SQL Server 結構 作業系統架構 堆疊大小
x86 (32 位元) x86 (32 位元) 512 KB
x86 (32 位元) x64 (64 位元) 768 KB
x64 (64 位元) x64 (64 位元) 2048 KB
IA64 (Itanium) IA64 (Itanium) 4096 KB

2 從 SQL Server 2012 (11.x) 開始,CLR 記憶體是由 max_server_memory 配置管理。

SQL Server 使用記憶體通知 API QueryMemoryResourceNotification 來判斷 SQL Server 記憶體管理員配置記憶體和釋放記憶體的時機。

啟動時,SQL Server 會根據系統的實體記憶體數量、伺服器執行緒數量、各種啟動參數等參數,計算緩衝集區的虛擬位址空間大小。 SQL Server 會替緩衝集區將計算出的處理虛擬位址空間量保留下來,但它只會取得 (認可) 目前負載所需的實體記憶體量。

該執行個體接著會繼續視需要取得記憶體,來支援工作負載。 連線和執行查詢的使用者較多時,SQL Server 會視需要取得更多實體記憶體。 SQL Server 執行個體會持續取得實體記憶體,直到達到最大伺服器記憶體 (MB) 配置目標,或 OS 指出已無可用記憶體;如果可用記憶體高於最小伺服器記憶體設定,且 OS 指出可用記憶體短缺時,SQL Server 執行個體會釋出記憶體。

當其他應用程式開始在執行 SQL Server 執行個體的電腦上執行時,它們會取用記憶體,並使可用實體記憶體的數量降到 SQL Server 目標以下。 SQL Server 執行個體會調整它的記憶體耗用量。 如果其他應用程式停止而有更多記憶體可供使用,SQL Server 執行個體就會增加其記憶體配置的大小。 SQL Server 每一秒鐘都可以釋放及取得數 MB 的記憶體,使它能隨記憶體配置的變更來快速調整。

最小與最大伺服器記憶體的作用

最小伺服器記憶體最大伺服器記憶體設定選項會建立緩衝集區以及資料庫引擎內其他快取所使用的記憶體數量上限與下限。 緩衝集區不會立即取得最小伺服器記憶體指定的記憶體數量。 緩衝集區只會以初始化所需的記憶體啟動。 工作負載增加後,SQL Server 資料庫引擎會持續取得支援工作負載所需的記憶體。 緩衝集區達到最小伺服器記憶體指定的數量前,不會釋放取得的任何記憶體。 一旦達到最小伺服器記憶體,緩衝集區便會使用標準演算法來視需要取得及釋放記憶體。 唯一的差別是緩衝集區的記憶體配置絕不降至低於最小伺服器記憶體指定的數量,也絕不取得高於 [最大伺服器記憶體 (MB)] 中指定的記憶體數量。

注意

SQL Server 作為處理序時,取得的記憶體比 [最大伺服器記憶體 (MB)] 選項指定的數量多。 內部和外部元件都可以在緩衝集區外部配置記憶體,這會取用額外的記憶體,但配置給緩衝集區的記憶體通常代表 SQL Server 所取用之記憶體的最大部分。

SQL Server 資料庫引擎取得的記憶體數量完全取決於執行個體的工作負載。 不處理許多要求時,SQL Server 執行個體可能永遠不會達到最小伺服器記憶體。

如果最小伺服器記憶體和最大伺服器記憶體 (MB) 指定相同的值,只要 SQL Server 資料庫引擎配置的記憶體達到該值,SQL Server 資料庫引擎就會停止動態釋放,並取得緩衝集區的記憶體。

如果 SQL Server 的執行個體在電腦上執行,而電腦上又有其他應用程式頻繁地停止或啟動的話,SQL Server 執行個體配置和取消配置記憶體,可能會延遲其他應用程式啟動的時間。 同時,如果 SQL Server 是單一電腦上數個執行伺服器應用程式中的一個,則系統管理員可能需要控制配置給 SQL Server 的記憶體數量。 這時,您可以使用最小伺服器記憶體和最大伺服器記憶體 (MB) 選項,控制 SQL Server 可以使用的記憶體。 [最小伺服器記憶體] 與 [最大伺服器記憶體] 選項以 MB 指定。 如需詳細資訊,包括如何設定這些記憶體設定的建議,請參閱伺服器記憶體設定選項

SQL Server 物件使用記憶體的規格

下表將列描述 SQL Server 中不同物件所使用的記憶體大約數量。 所列的數量為估計值,且會因環境及建立物件的方式而有所不同:

  • 鎖定 (由鎖定管理員保留):64 位元組 + 每位擁有者 32 位元組
  • 使用者連線:大約 (3 * network_packet_size + 94 KB)

網路封包大小是表格式資料流 (TDS) 封包大小,用來建立應用程式與資料庫引擎間的通訊。 預設封包大小是 4 KB,由 network packet size 組態選項所控制。

啟用 Multiple Active Result Set (MARS) 後,使用者連線大約為 (3 + 3 * num_logical_connections) * network_packet_size + 94 KB。

min memory per query 的作用

min memory per query 設定選項會建立為執行查詢所配置的最小記憶體數量 (以 KB 為單位)。 這也稱為最小記憶體授與。 所有查詢都必須等到可取得要求的最小記憶體、執行可以開始前,或超過查詢等候伺服器設定選項中指定的值為止。 此案例累積的等候類型是 RESOURCE_SEMAPHORE

重要

請勿將每次查詢的最小記憶體伺服器設定選項設得太高,特別是在非常忙碌的系統上,因為這樣做可能導致:

  • 記憶體資源的競用情況增加。
  • 藉由增加每個單一查詢的記憶體數量會減少並行處理,即使執行階段所需的記憶體比此設定低也一樣。

如需使用此設定的建議,請參閱設定 min memory per query 伺服器設定選項

記憶體授與考量

如果是資料列模式執行,任何情況都不得超過初始記憶體授與。 如果需要比初始授與更多的記憶體才能執行雜湊排序作業,則這些作業會溢出至磁碟。 tempdb 的工作檔案支援溢寫的雜湊作業,工作資料表則支援溢寫的排序作業。

排序作業期間發生的溢寫稱為排序警告。 排序警告會指出不符合記憶體的排序作業。 但這不包括建立索引的排序作業,只有查詢中的排序作業 (例如 SELECT 陳述式中使用的 ORDER BY 子句)。

雜湊作業期間發生的溢寫稱為雜湊警告。 當雜湊作業期間發生雜湊遞迴或雜湊停止 (雜湊釋出) 時,就會發生這些情況。

  • 建立輸入不符合可用記憶體時,會發生雜湊遞迴,因而將輸入分割為多個需要個別處理的資料分割。 如果這些資料分割中仍有任何資料分割不符合可用記憶體,則這些資料分割會再分割成子資料分割,且仍是需要個別處理。 這個分割處理會繼續進行,直到每個資料分割都符合可用記憶體或達到最大遞迴層級為止。
  • 當雜湊作業達到最大遞迴等級時會發生 Hash Bailout,且切換到其他計畫以處理其他的分割資料。 這些事件會導致您的伺服器效能降低。

針對批次模式執行,根據預設,初始記憶體授與最高可動態增加到特定內部閾值。 此動態記憶體授與機制的設計是為了允許雜湊排序作業的記憶體駐留執行在批次模式中執行。 如果這些作業仍不符合記憶體,這些輸入會溢寫至磁碟。

如需執行模式的詳細資訊,請參閱查詢處理架構指南

緩衝區管理

SQL Server 資料庫的主要用途是為了儲存和抓取資料,因此大量磁碟 I/O 是 Database Engine 的核心特性。 此外,因為磁碟 I/O 作業會取用許多資源,而且相對上需要較長的時間才能完成,所以 SQL Server 非常著重提高 I/O 的效率。 緩衝區管理是達成這種效率的重要元件。 緩衝區管理元件包含兩種機制:可存取及更新資料庫分頁的緩衝區管理員,以及可降低資料庫檔案 I/O 的緩衝快取 (也稱為緩衝集區)。

緩衝區管理如何運作

緩衝區是 8 KB 的記憶體頁面,大小與資料或索引頁面相同。 因此,緩衝區快取也分成 8 KB 的頁面。 緩衝區管理員管理從資料庫磁碟檔案將資料或索引頁面讀取到緩衝快取中,以及將修改後頁面重新寫入磁碟的功能。 頁面會保留在緩衝區快取中,直到緩衝區管理員需要緩衝區來讀取更多資料為止。 只有資料修改後,才會重新寫入磁碟。 在重新寫入磁碟之前,可以多次修改緩衝區快取中的資料。 如需詳細資訊,請參閱 讀取分頁寫入分頁

啟動時,SQL Server 會根據數種參數 (例如系統的實體記憶體數量、最大伺服器執行緒設定的數量以及各種啟動參數) 計算緩衝集區快取虛擬位址空間的大小。 SQL Server 會替緩衝快取保留此計算所得的處理虛擬位址空間量 (稱為記憶體目標),但它只會取得 (認可) 目前負載所需的實體記憶體量。 您可以在 sys.dm_os_sys_info 目錄檢視中查詢 committed_target_kbcommitted_kb 資料行,以分別傳回保留為記憶體目標的頁數和緩衝集區快取目前認可的頁數。

從 SQL Server 啟動到緩衝快取取得記憶體目標時的這段期間稱為「擴置」(Ramp-up)。 在這段期間,讀取要求會依需要填滿緩衝區。 例如,讀取單頁 8 KB 的要求會填滿單一緩衝區分頁。 這表示擴置是依據用戶端要求的數目和類型而定。 擴大會將讀取單頁要求,轉換成對齊的八頁要求 (組成一個範圍) 來加速。 這可讓擴置加快完成,特別是在具有大量記憶體的電腦上。 如需分頁和範圍的詳細資訊,請參閱分頁與範圍結構指南

因為緩衝區管理員要使用 SQL Server 處理序中大部分的記憶體,所以會與記憶體管理員合作以允許其他元件使用其緩衝區。 緩衝區管理員主要與下列元件進行互動:

  • 資源管理員會控制整體記憶體使用量,並在 32 位元平台中控制位址空間使用量。
  • 適用於低階檔案 I/O 作業的資料庫管理員和 SQL Server 作業系統 (SQLOS)。
  • 預寫記錄檔的記錄管理員。

支援的功能

緩衝區管理員支援下列功能:

  • 緩衝區管理員可知曉非統一記憶體存取 (NUMA) 。 緩衝快取頁面會分散到硬體 NUMA 節點,這可讓執行緒存取本機 NUMA 節點上配置的緩衝區頁面,而不是從外部記憶體中存取。

  • 緩衝區管理員支援 [熱新增記憶體],讓使用者無須重新啟動伺服器即可增加實體記憶體。

  • 緩衝區管理員在 64 位元平台上支援大型分頁。 Windows 的不同版本各有特定的頁面大小。

    注意

    在 SQL Server 2012 (11.x) 之前,在 SQL Server 中啟用大型分頁需要追蹤旗標 834

  • 緩衝區管理員會提供透過動態管理檢視公開的額外診斷資訊。 您可以使用這些檢視監視 SQL Server 特定的各種作業系統資源。 例如,您可使用 sys.dm_os_buffer_descriptors 檢視來監視緩衝區快取中的分頁。

磁碟 I/O

緩衝區管理員僅針對資料庫執行讀取和寫入。 其他檔案及資料庫作業,如開啟、關閉、擴充和壓縮,都是由資料庫管理員和檔案管理員元件來執行。

緩衝區管理員執行的磁碟 I/O 作業具有下列特性:

  • 所有的 I/O 都是以非同步的方式進行,這可讓呼叫執行緒繼續進行處理,而 I/O 作業則同時於背景中執行。
  • 除非使用親和性 I/O 選項,否則所有 I/O 都是在呼叫執行緒中發出。 關連 I/O 遮罩選項會將 SQL Server 磁碟 I/O 繫結到指定的 CPU 子集。 在高階的 SQL Server 線上交易處理 (OLTP) 環境中,此延伸模組可強化 SQL Server 執行緒發出 I/O 的效能。
  • 多頁 I/O 是透過散佈 - 收集 I/O 來完成,可讓資料轉入或轉出非連續的記憶體區域。 這表示 SQL Server 可以快速填滿或排清緩衝快取,同時還能避免多個實體 I/O 要求。

長 I/O 要求

緩衝區管理員會報告任何至少持續 15 秒仍未處理的 I/O 要求。 這樣可以協助系統管理員區別 SQL Server 問題和 I/O 子系統問題。 報告錯誤訊息 833,並如 SQL Server 錯誤記錄中所顯示:

SQL Server has encountered ## occurrence(s) of I/O requests taking longer than 15 seconds to complete on file [##] in database [##] (#). The OS file handle is 0x00000. The offset of the latest long I/O is: 0x00000.

長 I/O 可以是讀取或寫入,但不會在目前的訊息中指出。 長 I/O 訊息是警告,而非錯誤。 讀取或寫入 I/O 都不會指出 SQL Server 的問題,但會指出基礎 I/O 系統的問題。 報告這些訊息的目的是在協助系統管理員更快找到 SQL Server 回應時間遲緩的原因,並區別 SQL Server 控制範圍之外的問題。 所以您不必採取任何動作,但系統管理員要調查 I/O 要求為什麼需要這麼長的時間,及該使用時間是否合理。

長 I/O 要求的原因

長 I/O 訊息可能指出 I/O 已遭永久封鎖且永遠無法完成 (稱為遺失 I/O),或只是仍未完成。 遺失 I/O 經常導致閂鎖逾時,但也無法從訊息中辨別實際狀況。

長 I/O 通常表示 SQL Server 工作負載對磁碟子系統而言有些過重。 出現下列情形時,可能表示磁碟子系統已經不勝負荷:

  • 在繁重的 SQL Server 工作負載期間,錯誤記錄出現多則長 I/O 訊息。
  • 效能監視計數器顯示長時間的磁碟延遲、冗長磁碟佇列,或沒有磁碟閒置時間。

長 I/O 也可能是 I/O 路徑中的元件 (例如,驅動程式、控制器或韌體) 所造成,因為這個元件持續延後對舊有 I/O 要求的服務,而優先服務較接近磁碟讀寫頭目前位置的較新要求。 以接近讀取/寫入頭目前位置的程度作為處理要求優先順序標準的常見技術,稱為「升降式尋找」。由於大部分的 I/O 都會立即提供,因此這種技術可能難以搭配效能監視器工具使用。 執行大量循序 I/O 的工作負載,如備份與還原、資料表掃描、排序、建立索引、大量載入以及清空檔案等作業,會使長 I/O 要求的情況惡化。

硬體或驅動程式問題可能造成與上述情況無關的孤立長 I/O。 系統事件記錄檔可能會包含有助於診斷問題的相關事件。

記憶體壓力偵測

記憶體壓力是記憶體短缺所造成的情況,可能會導致:

  • 額外的 I/O (例如非常活躍的延遲寫入器背景執行緒)
  • 重新編譯率偏高
  • 查詢的執行時間變長 (如果存在記憶體授與等候)
  • 額外的 CPU 週期

觸發此情況的原因可能來自外部,也可能來自內部。 外部原因包括:

  • 可用的實體記憶體 (RAM) 不足。 這會導致系統修剪目前執行中處理序的工作集,而可能造成整體速度變慢。 SQL Server 可能減少緩衝集區的認可目標,並開始更頻繁地修剪內部快取。
  • 整體可用的系統記憶體 (包括系統分頁檔) 不足。 這可能會導致系統記憶體配置失敗,因為它無法分頁目前已配置的記憶體。

內部原因包括:

  • 設定較低的記憶體使用量上限時,SQL Server 資料庫引擎會回應外部記憶體壓力。
  • 記憶體設定已透過降低 max server memory 設定手動降低。
  • 數個快取之間的內部元件記憶體分配有所變更。

SQL Server 資料庫引擎會實作專門用來偵測並處理記憶體壓力的架構,作為動態記憶體管理的一部分。 此架構包含稱為資源監視器的背景工作。 資源監視器工作會監視外部和內部記憶體指標的狀態。 一旦其中一個指標變更狀態,就會計算對應的通知並予以廣播。 這些通知是來自每個引擎元件的內部訊息,並會儲存在信號緩衝區中。

有兩個信號緩衝區會保存與動態記憶體管理相關的資訊:

  • 資源監視器信號緩衝區,它會追蹤資源監視器活動,例如是否發出記憶體壓力信號。 此信號緩衝區會根據目前條件為 RESOURCE_MEMPHYSICAL_HIGHRESOURCE_MEMPHYSICAL_LOWRESOURCE_MEMPHYSICAL_STEADYRESOURCE_MEMVIRTUAL_LOW 來包含狀態資訊。
  • 記憶 Broker 信號緩衝區,其中包含每個 Resource Governor 資源集區的記憶體通知記錄。 偵測到內部記憶體壓力時,系統會針對配置記憶體的元件開啟記憶體不足通知,以觸發動作來平衡快取之間的記憶體。

記憶 Broker 會監視每個元件的記憶體使用量需求,然後根據所收集的資訊,計算每個元件的最佳記憶體值。 每個 Resource Governor 資源集區會有一組 Broker。 這項資訊會接著廣播到每個元件,並視需要縮放其使用量。

如需記憶 Broker 的詳細資訊,請參閱 sys.dm_os_memory_brokers

錯誤偵測

為了確保分頁從寫入磁碟到再次讀取時的完整性,資料庫分頁可以使用兩個選用機制的其中一種:損毀分頁保護或總和檢查碼保護。 這些機制讓獨立的方法,不僅可以確認資料儲存媒體的正確性,而且也可以驗證硬體元件,如控制器、驅動程式、纜線,甚至作業系統。 這個保護會在頁面寫入磁碟之前加諸頁面,並在從磁碟讀取頁面之後進行驗證。

讀取因總和檢查碼、損毀分頁或其他 I/O 錯誤失敗後,SQL Server 會重試讀取四次。 如果任何一次重試讀取成功,都會將訊息寫入錯誤記錄檔中,且會繼續觸發讀取作業的命令。 如果重試失敗,此命令便會失敗,且會出現錯誤訊息 824。

頁面使用的保護類型是含有該頁面之資料庫的屬性。 總和檢查碼保護是 SQL Server 2005 (9.x) 和更新版本建立資料庫時預設的保護。 分頁保護機制是在資料庫建立時指定,並可以使用 ALTER DATABASE SET 變更。 您可查詢 sys.databases 目錄檢視中的 page_verify_option 資料行,或查詢 DATABASEPROPERTYEX 函式的 IsTornPageDetectionEnabled 屬性,來判斷目前的分頁保護設定。

注意

如果變更頁面保護設定,新的設定並不會立即影響整個資料庫。 反而每當頁面有資料寫入時,這些頁面還是會採用目前的資料庫保護等級。 這表示資料庫可能會由具有不同保護類型的頁面組成。

損毀頁保護

SQL Server 2000 (8.x) 採用的損毀分頁保護,是偵測停電導致分頁損毀的主要方法。 例如,非預期的電源故障可能造成只有部分的頁面寫入磁碟。 使用損毀頁保護時,會在分頁寫入磁碟時,將 8 KB 的資料庫分頁中的每 512 位元組磁區之特定 2 位元簽章模式,儲存至資料庫頁首中。

當從磁碟中讀取頁面時,會比較頁首中所儲存的損毀位元和實際的頁面磁區資訊。 簽章模式會在每次寫入時交替使用二進位數 0110,因此總是可以判斷何時未將磁區完整寫入磁碟:如果稍後讀取分頁時,位元處於錯誤的狀態,即代表分頁寫入不正確,因而偵測到損毀頁。 損毀分頁偵測使用最少的資源,但無法偵測磁碟硬體失敗造成的錯誤。 如需設定損毀分頁偵測的資訊,請參閱 ALTER DATABASE SET 選項 (Transact-SQL)

總和檢查碼保護

SQL Server 2005 (9.x) 採用總和檢查碼保護,提供更強的資料完整性檢查。 總和檢查碼會針對每個頁面中寫入的資料來計算,並且儲存在頁面標頭中。 每當從磁碟讀取具有已儲存總和檢查碼的頁面時,資料庫引擎會在頁面中重新計算資料的總和檢查碼,如果新的總和檢查碼與儲存的總和檢查碼不同,即引發錯誤 824。 總和檢查碼保護可以比損毀頁保護捕捉更多的錯誤,因為頁面的每個位元組都會牽動它,不過相對上也需要大量的資源。

啟用總和檢查碼時,緩衝區管理員任何時間從磁碟讀取頁面,都能偵測到因電源故障和有缺陷硬體或韌體所造成的錯誤。 如需設定總和檢查碼的資訊,請參閱 ALTER DATABASE SET 選項 (Transact-SQL)

重要

升級為 SQL Server 2005 (9.x) 或更新版本時,使用者或系統資料庫會保留 PAGE_VERIFY 值 (NONETORN_PAGE_DETECTION)。 強烈建議您使用 CHECKSUMTORN_PAGE_DETECTION 可以使用較少資源,但提供 CHECKSUM 的子集保護最少。

了解非統一記憶體存取

SQL Server 會感知非統一記憶體存取 (NUMA),而且不需要特殊組態,就可以在 NUMA 硬體上順利執行。 隨著處理器時脈和數目的增加,要降低使用此額外處理能力所需要的記憶體延遲變得越來越困難。 為了避免這個狀況,硬體供應商提供了大型的 L3 快取,但這只是有限的解決方案。 NUMA 架構對這個問題提供了可擴充的解決方案。

SQL Server 已設計成可利用 NUMA 電腦的優點,而不需要進行任何應用程式變更。 如需詳細資訊,請參閱如何:設定 SQL Server 使用軟體 NUMA

記憶體物件的動態分割

堆積配置器 (在 SQL Server 中稱為記憶體物件) 讓資料庫引擎可從堆積配置記憶體。 您可以使用 sys.dm_os_memory_objects DMV 來追蹤這些物件。

CMemThread 是安全執行緒的記憶體物件類型,允許從多個執行緒進行並行記憶體配置。 為了正確追蹤,CMemThread 物件依賴同步處理建構 (Mutex) 來確保一次只有一個執行緒更新重要的資訊片段。

注意

CMemThread 物件類型可用於許多不同配置的資料庫引擎程式碼基底,並可透過節點或 CPU 進行全域分割。

不過,如果有許多執行緒是以高度並行的方式從相同的記憶體物件配置,則 mutex 的使用可能會導致爭用。 因此,SQL Server 具備分割記憶體物件 (PMO) 概念,並以單一 CMemThread 物件表示每個分割區。 記憶體物件的資料分割會以靜態方式定義,而且建立後無法變更。 由於記憶體配置模式根據硬體和記憶體使用量等方面而有很大的差異,因此無法預先提供完美的資料分割模式。

在大部分的情況下,使用單一分割區即足夠,但在部分案例中,單一分割區可能導致競爭,只有在高度分割的記憶體物件才能避免這種情況。 我們不建議分割每個記憶體物件,因為多個分割區可能導致其他部分效率不足,並增加記憶體片段。

注意

在 SQL Server 2016 (13.x) 之前,追蹤旗標 8048 可用來強制節點型 PMO 作為 CPU 型 PMO。 從 SQL Server 2014 (12.x) SP2 和 SQL Server 2016 (13.x) 開始,此行為是由引擎動態控制。

從 SQL Server 2014 (12.x) SP2 和 SQL Server 2016 (13.x) 開始,資料庫引擎可以動態偵測特定 CMemThread 物件上的競爭,並將物件升階為每個節點型或每個 CPU 型的實作。 升階後,PMO 會保持升階,直到重新啟動 SQL Server 處理序。 sys.dm_os_wait_stats DMV 中是否有高 CMEMTHREAD 等候,以及透過觀察 sys.dm_os_memory_objects DMV 資料行 contention_factorpartition_typeexclusive_allocations_countwaiting_tasks_count,都可以偵測到 CMemThread 爭用。

下一步