Sql-Server

由於從多個數據庫創建高並發臨時表而導致 tempdb 爭用?

  • June 6, 2018

我有一個包含約 100 個數據庫的環境,所有數據庫都具有相同的架構。每個數據庫上都有一個儲存過程,它創建一個 #temp 表並將其刪除,並且執行非常頻繁(每個使用者每 30 秒左右,並且有 1000 多個使用者)。它所做的遠不止這些:我們將潛在的數千行載入到這個臨時表中,然後將整個內容轉儲出去,基本上它聚合了一堆數據。

由於所有數據庫都創建相同的臨時表,它們是否都相互競爭?還是每個數據庫在 tempdb 中都有自己的臨時表版本?

似乎他們有爭用,因為我看到大量PAGE_LATCH等待,都在 tempdb ( 2:3:1041580) 的同一頁面上,這不是 GAM、SGAM 或 PFS 頁面,而且 90% 的等待似乎來自同一個頁面跨所有數據庫的儲存過程。這些等待佔伺服器上總等待的 90%,並導致阻塞。

我做了一個DBCC PAGE,它似乎是sysobjvalues(來自標題中的 object_ID 60)。我跑了:

SELECT OBJECT_Name(object_ID), * 
FROM sys.dm_db_database_page_allocations(2,60,NULL,NULL,'DETAILED')

我得到 153 行,不確定我在這裡看到的是什麼。看起來它是IN_ROW_DATALOB_DATAin allocation_unit_type_desc

我在與其他文件不同的捲上有 8 個 tempdb 文件。我有 16 個核心,但我的理解是,由於它不是分配頁面,因此可能無助於增加文件數量。使用 SQL Server 2017 企業版。

我覺得最好的辦法是告訴開發人員在這裡刪除臨時表,但這需要重新設計邏輯並且需要一些時間。在等待開發修復時,我還能做些什麼來避免這些頁面閂鎖嗎?

我們可能會將數千行載入到這個臨時表中,然後將整個內容轉儲出去,基本上它聚合了一堆數據。

如果使用得當,臨時表可以在性能和可靠性方面取得巨大的勝利。

例如,在臨時表中儲存相對較小(且範圍較窄)的中間結果集非常有用,這樣 SQL Server 可以計算數據的自動統計資訊,或者使用者可以添加特定的索引。

當臨時表允許優化器生成比單個整體查詢更好的總體計劃序列時,它們最有用。

也有可能不好地使用臨時表。在“傾倒整個事情”之前將行簡單地儲存在臨時表中聽起來適得其反。始終牢記臨時表不是免費的,並且可能導致爭用。

除了以合理的方式使用臨時表之外,請嘗試安排事情以便利用臨時表記憶體。有關詳細資訊,請參閱我的文章SQL Server 臨時對象記憶體

確保您正在執行最新的累積更新,因為已經採用了多項性能優化和錯誤修復,例如:

TempDB 是一種共享資源,因此在某種程度上,是的,所有會話都在競爭該資源。但是,這與表名相同無關,因為 SQL Server 將一組唯一的字元附加到每個本地臨時表名的末尾。它通常與創建/刪除臨時表以及對這些表的 DML 操作有關(如果您使用快照隔離,那麼它將tempdb用於版本儲存,而觸發器tempdb用於inserteddeleted表)。

我不認為臨時表本身就是問題,因為“每 30 秒一次”並不像您想像的那麼頻繁。我曾在每秒處理數千個事務以及大量使用臨時數據庫的系統上工作過。

我會看:

  1. 該臨時表正在做什麼?有多少數據被載入到其中?有很多更新嗎?如果有很多行,也許添加索引會有所幫助?
  2. 臨時表是在事務中創建的嗎?是在顯式事務(即BEGIN TRAN)中還是在觸發器中?如果是,那麼我已經看到這種情況導致阻塞。最好在事務之外創建臨時表,一旦創建,然後在事務中執行 DML 語句。

此外,由於您使用的是 SQL Server 2017 Enterprise,您或許可以考慮使用記憶體中 OLTP 來換出基於磁碟的臨時表。我相信它將創建一個記憶體中使用者定義的表類型,然後從該 UDTT 創建一個表變數。

引用自:https://dba.stackexchange.com/questions/208825