SQLSERVER Tempdb的作用及優化
tempdb 系統數據庫是可供連接到 SQL Server 實例的所有用戶使用的全局資源。tempdb 數據庫用於存儲下列對象:用戶對象、內部對象和版本存儲區。
用戶對象
用戶對象由用戶顯式創建。這些對象可以位於用戶會話的作用域中,也可位於創建對象所用例程的作用域中。例程可以是存儲過程、觸發器或用戶定義函數。用戶對象可以是下列項之一:
-
用戶定義的表和索引
-
系統表和索引
-
全局臨時表和索引
-
局部臨時表和索引
-
table 變量
-
表值函數中返回的表
內部對象
內部對象是根據需要由 SQL Server 數據庫引擎創建的,用於處理 SQL Server 語句。內部對象可以在語句的作用域中創建和刪除。內部對象可以是下列項之一:
-
用於遊標或假脫機操作以及臨時大型對象 (LOB) 存儲的工作表。
-
用於哈希聯接或哈希聚合操作的工作文件。
-
用於創建或重新生成索引等操作(如果指定了 SORT_IN_TEMPDB)的中間排序結果,或者某些 GROUP BY、ORDER BY 或 UNION 查詢的中間排序結果。
每個內部對象至少使用九頁;一個 IAM 頁,一個八頁的區。有關頁和區的詳細信息,請參閱頁和區。
下表列出了 SQL Server 中創建 tempdb 的用戶對象、內部對象或行版本的功能。只要有可能,便會提供估計磁盤空間使用量的方法。
功能 |
tempdb 使用 |
其他信息 |
---|---|---|
啟用了觸發器的大容量加載操作 |
啟用觸發器後便可使用大容量導入優化。SQL Server 將針對更新或刪除事務的觸發器使用行版本控制。每個刪除或更新的行的副本都會添加到版本存儲區中。請參閱此表後面部分中的“觸發器”。 |
優化大容量導入性能 |
公用表表達式查詢 |
公用表表達式可以認為是在單個 SELECT、INSERT、UPDATE、DELETE 或 CREATE VIEW 語句的執行範圍內定義的臨時結果集。 當公用表表達式查詢的查詢計劃使用 Spool 運算符保存中間查詢結果時,數據庫引擎會在 tempdb |
使用公用表表達式 WITH common_table_expression (Transact-SQL) |
遊標 |
鍵集驅動遊標和靜態遊標使用在 tempdb 中生成的工作表。鍵集驅動遊標使用工作表來存儲標識遊標中各行的鍵集。靜態遊標使用工作表來存儲遊標的完整結果集。 如果選擇的查詢計劃不同,則遊標的磁盤空間使用量也可能會不同。如果查詢計劃與早期版本 SQL Server 中的查詢計劃相同,則磁盤空間使用量也大致相同。 |
關於選擇遊標類型 |
數據庫郵件 |
請參閱此表後面部分中的“Service Broker”。 |
數據庫郵件 |
DBCC CHECKDB |
DBCC CHECKDB 使用 tempdb 工作表來保存中間結果或進行排序操作。 若要確定操作的 tempdb 磁盤空間要求,請運行 DBCC CHECKDB WITH ESTIMATEONLY。 |
DBCC CHECKDB (Transact-SQL) 優化 DBCC CHECKDB 性能 |
事件通知 |
請參閱此表後面部分中的“Service Broker”。 |
了解事件通知 |
索引 |
當創建或重新生成索引(脫機或聯機)並將 SORT_IN_TEMPDB 選項設置為 ON 時,可以引導數據庫引擎使用 tempdb 來存儲用於生成索引的中間排序結果。如果指定了 SORT_IN_TEMPDB 並需要進行排序,則 tempdb必須具有足以包含最大索引的磁盤空間,另外還必須具有大小等於 index create memory 選項的值的磁盤空間。有關詳細信息,請參閱索引磁盤空間示例。 表和索引可以進行分區。對於已分區索引,如果指定了 SORT_IN_TEMPDB 索引選項並且索引與基表對齊,則 tempdb 中具有的空間必須足以容納最大分區的中間排序段。如果索引未對齊,則 tempdb 中具有的空間必須足以容納所有分區的中間排序段。有關詳細信息,請參閱已分區索引的特殊指導原則。 聯機索引操作使用行版本控制來使索引操作不受其他事務所做的修改的影響。行版本控制不需要對已讀取的行請求共享鎖。在聯機索引操作期間,並發的用戶更新和刪除操作需要一定的空間以用於 tempdb 中的版本記錄。如果聯機索引操作使用 SORT_IN_TEMPDB 並需要進行排序時,則 tempdb 除了具有用於先前所述的中間排序結果的磁盤空間之外,還必須具有額外的磁盤空間。創建、刪除或重新生成聚集索引的聯機索引操作也需要額外的磁盤空間來生成並維護臨時映射索引。CREATE 和 UPDATE STATISTICS 操作可以使用 tempdb 來將行樣本排序以便生成統計信息。有關詳細信息,請參閱索引 DDL 操作的磁盤空間要求。 |
tempdb 和索引創建 已分區索引的特殊指導原則 索引 DDL 操作的磁盤空間要求 索引磁盤空間示例 聯機索引操作的工作方式 |
大型對象 (LOB) 數據類型變量和參數 |
大型對象數據類型包括 varchar(max)、nvarchar(max)、varbinary(max)、text、ntext、image 和 xml。這些類型的最大大小可達 2 GB,並可在存儲過程、用戶定義函數、批處理或查詢中用作變量或參數。定義為 LOB 數據類型的參數和變量在值很小的情況下將使用主內存作為存儲區。但是,較大值將存儲在 tempdb 中。當 LOB 變量和參數存儲在 tempdb 中時,可以將它們視為內部對象。您可以查詢 sys.dm_db_session_space_usage 動態管理視圖,以報告針對給定會話分配給內部對象的頁。 有些內部字符串函數(例如,SUBSTRING 或 REPLICATE)在針對 LOB 值執行操作時,可能需要在 tempdb 中進行中間臨時存儲。同樣,如果對數據庫啟用了基於行版本控制的事務隔離級別並且對大型對象進行了修改,則 LOB 的已更改片段將被復制到 tempdb 的版本存儲區中。 |
使用大值數據類型 |
多個活動的結果集 (MARS) |
單個連接下可以出現多個活動結果集,這通常稱為 MARS。如果 MARS 會話在存在活動結果集的情況下發出數據修改語句(例如 INSERT、UPDATE 或 DELETE),則將受到修改語句影響的行存儲在 tempdb 的版本存儲區中。請參閱此表後面部分中的“行版本控制”。 |
使用多個活動的結果集 (MARS) |
查詢通知 |
請參閱此表後面部分中的“Service Broker”。 |
使用查詢通知 |
查詢 |
包含 SELECT、INSERT、UPDATE 和 DELETE 語句的查詢可以使用內部對象來存儲哈希聯接、哈希聚合或排序的中間結果。 緩存查詢執行計劃時,也會緩存計劃所需的工作表。緩存工作表時,該表會截斷,並且緩存中保留九頁以便重用。這樣可提高下次執行查詢時的性能。如果系統內存不足,則數據庫引擎可以刪除執行計劃以及關聯的工作表。 |
執行計劃的緩存和重新使用 |
行版本控制 |
行版本控制是用於支持下列功能的常規框架:
行版本在活動事務必須對其進行訪問時一直保存在 tempdb 版本存儲區中。當前版本存儲區的內容在 sys.dm_tran_version_store 中返回。由於版本存儲區頁是全局資源,所以在文件級別對其進行跟蹤。您可以使用 sys.dm_db_file_space_usage 中的 version_store_reserved_page_count 列來查看版本存儲區的當前大小。版本存儲區清除必須考慮需要訪問特定版本的運行時間最長的事務。可通過查看 sys.dm_tran_active_snapshot_database_transactions 中的 elapsed_time_seconds 列來發現與版本存儲區清除相關的運行時間最長的事務。可以使用 Transactions 對象中的 Free Space in Tempdb (KB) 和 Version Store Size (KB) 計數器來監視 tempdb 中行版本存儲區的大小和增長速率。有關詳細信息,請參閱 SQL Server Transactions 對象。 若要估計 tempdb 中行版本控制所需的空間量,請務必先考慮活動事務必須將其所有更改保留在版本存儲區中。這意味著稍後啟動的快照事務可以訪問舊版本。此外,如果存在活動的快照事務,則由快照啟動時處於活動狀態的事務生成的所有版本存儲區數據也必須保留。 下面是基本公式: [Size of Version Store] = 2 * [Version store data generated per minute] * [Longest running time (minutes) of your transaction] |
了解基於行版本控制的隔離級別 行版本控制資源的使用情況 |
Service Broker |
Service Broker 可幫助開發人員構建異步的松散耦合應用程序,在這些應用程序中彼此獨立的組件相互配合來完成一項任務。這些應用程序組件將交換包含完成任務所需的信息的消息。Service Broker 顯式使用 tempdb 來保留內存中無法保留的現有對話框上下文。每個對話框的大小大約為 1 KB。 此外,Service Broker 將隱式使用 tempdb 在查詢執行上下文中緩存對象(例如,用於計時器事件和後臺傳遞會話的工作表)。 數據庫郵件、事件通知和查詢通知將隱式使用 Service Broker。 |
概述 (Service Broker) |
存儲過程 |
存儲過程可以創建用戶對象,例如全局臨時表或局部臨時表及其索引、變量或參數。可以緩存存儲過程中的臨時對象以優化刪除和創建這些對象的操作。這一行為會增加 tempdb 磁盤空間要求。每個臨時對象可最多存儲九頁以便重用。請參閱此表後面部分中的“臨時表和 table 變量”。 |
創建存儲過程(數據庫引擎) |
臨時表和 table 變量
|
臨時表和 table 變量存儲在 tempdb 中。臨時表對象的磁盤空間要求與早期版本的 SQL Server 中的要求相同。估計臨時表大小的方法與估計標準表大小的方法相同。有關詳細信息,請參閱估計表的大小。 table 變量的行為類似於局部變量。table 變量的類型為 table,主要用於臨時存儲作為表值函數結果集返回的行集。保存 table 變量所需的磁盤空間取決於聲明變量以及變量中存儲的值的大小。 當滿足下列條件時會緩存本地臨時表和變量:
緩存臨時表或 table 變量時,在臨時對象完成使命時沒有將其刪除。相反,臨時對象將截斷。臨時對象可最多存儲九頁,以便在下次執行調用時重用。通過緩存,刪除和創建對象的操作可以非常快速地執行,並可減少頁分配爭用。 為了獲得最佳性能,應該使用以下公式計算 tempdb 中的緩存本地臨時表或 table 變量所需的磁盤空間: 9 page per temp table * number of average temp tables per procedure * number of maximum simultaneous executions of the procedure |
CREATE TABLE (Transact-SQL) 使用變量和參數(數據庫引擎) DECLARE @local_variable (Transact-SQL) |
觸發器 |
在 tempdb 中創建 AFTER 觸發器中使用的 inserted 和 deleted 表。即,由觸發器更新或刪除的行應進行版本控制。這包括由觸發觸發器的語句修改的所有行。由觸發器插入的行不進行版本控制。 INSTEAD OF 觸發器使用 tempdb 的方式類似於查詢所使用的方式。INSTEAD OF 觸發器的磁盤空間使用量與早期版本的 SQL Server 中的使用量相同。請參閱此表前面部分中的“查詢”。 當您在啟用觸發器的情況下大容量加載數據時,將向版本存儲區添加每一刪除行或更新行的一份副本。 |
CREATE TRIGGER (Transact-SQL) 優化大容量導入性能 行版本控制資源的使用情況 |
用戶定義函數 |
用戶定義函數可以創建臨時用戶對象,例如全局臨時表或局部臨時表及其索引、變量或參數。例如,表值函數的返回表存儲在 tempdb 中。 允許對標量函數和表值函數中的參數和返回值使用的數據類型包括大多數 LOB 數據類型。例如,返回值的類型可以為 xml 或 varchar(max)。請參閱此表前面部分中的“大型對象 (LOB) 數據類型變量和參數”。 可以緩存用戶定義表值函數中的臨時對象以優化刪除和創建這些對象的操作。請參閱此表前面部分中的“臨時表和 table 變量”。 |
CREATE FUNCTION (Transact-SQL) |
XML |
類型為 xml 的變量和參數最大大小可達 2 GB。只要值比較小,它們便會使用主內存作為存儲區。但是,較大值將存儲在 tempdb 中。請參閱此表前面部分中的“大型對象 (LOB) 數據類型變量和參數”。 sp_xml_preparedocument 系統存儲過程會在 tempdb 中創建一個工作表。MSXML 分析器使用該工作表來存儲已分析的 XML 文檔。執行存儲過程時,tempdb 的磁盤空間要求幾乎與指定的 XML 文檔的大小成正比。 |
實現 SQL Server 中的 XML sp_xml_preparedocument (Transact-SQL) 使用 OPENXML 查詢 XML |
確定 tempdb 在生產環境中的適當大小取決於多種因素。如本主題中前面所述,這些因素包括現有工作負荷以及使用的 SQL Server 功能。建議您通過在 SQL Server 測試環境中執行下列任務來分析現有的工作負荷:
-
設置 tempdb 的自動增長。
-
執行單獨的查詢或工作負荷跟蹤文件,監視 tempdb 空間使用。
-
執行索引維護操作(例如,重新生成索引),監視 tempdb 空間。
-
使用前面步驟中的空間使用值來預測總的工作負荷使用情況;針對計劃的並發活動調整此值,然後相應地設置 tempdb 的大小。
優化 tempdb 性能
tempdb 數據庫的大小和物理位置可能會影響系統的性能。例如,如果為 tempdb 定義的大小過小,則每次重新啟動 SQL Server 實例時,都可能會占用部分系統處理負荷,以使 tempdb 自動增長到支持工作負荷所需的大小。您可以通過增加 tempdb 數據和日誌文件的大小來避免此開銷。有關確定 tempdb 所需的適當磁盤空間量的信息
-
將文件增量設置為合理的大小以避免 tempdb 數據庫文件的增量過小。如果文件的增量與寫入 tempdb 的數據量相比過小,則 tempdb 可能需要不斷擴大。這將影響性能。建議為 tempdb 文件設置 FILEGROWTH 增量時遵循以下通用原則。
tempdb 文件大小
FILEGROWTH 增量
0 至 100 MB
10 MB
100 至 200 MB
20 MB
200 MB 或更多
10%*
* 您可能必須基於 tempdb 文件所在的 I/O 子系統的速度調整此百分比。為了避免潛在的閂鎖超時,我們建議將自動增長操作限制在大約兩分鐘之內。例如,如果 I/O 子系統以每秒 50 MB 的速度初始化文件,則無論 tempdb 文件的大小如何,FILEGROWTH 增量都應設置為最大值 6 GB。如果可能,請使用實例數據庫文件初始化來提高自動增長操作的性能。
-
通過將文件大小設置為足夠容納環境中典型工作負荷的值來預分配所有 tempdb 文件的空間。這可以避免 tempdb 因擴展得過於頻繁而影響性能。tempdb 數據庫應設置為自動增長,但是在出現意外情況時此設置將用於增加磁盤空間。
-
根據需要創建足夠多的文件以使磁盤寬度最大化。使用多個文件可以減少 tempdb 存儲爭用並獲得更大的可伸縮性。但是,請勿創建過多的文件,因為此操作可能降低性能並增加管理開銷。作為通用原則,為服務器中的每一個 CPU 創建一個數據文件(用於解釋任何關聯掩碼設置),然後根據需要上下調整文件的數量。請註意,雙核心 CPU 將被視為兩個 CPU。
-
使每個數據文件的大小相同,這樣可以優化比例填充的性能。
-
將 tempdb 數據庫放置在快速 I/O 子系統中。如果有許多直接連接的磁盤,則請使用磁盤條帶化。
-
將 tempdb 數據庫放置在用戶數據庫使用的磁盤以外的磁盤中。
SQLSERVER Tempdb的作用及優化