SQL Server 表上不可預測的單次插入性能
我繼承了一個有時表現出極差的單記錄插入性能的系統。
該表大約有 800 萬行,因此相對較大,但並非特別大。以下簡單的插入花費了 7 多分鐘,並在此過程中阻塞了整個系統:
INSERT INTO dbo.Communication(comm_action,comm_channelid,...) VALUES (N'Deskwork',11,...)
整體數據庫設計相當差。例如,儘管這個特定的表確實有一個聚集索引,但它也有 34 個其他索引,儘管它是一個具有大量插入/更新活動的 OLTP 系統。
我看不到任何觸發器,並且插入的性能在大多數情況下都相當不錯。好是一個相對的術語。
索引的數量真的可以解釋如此糟糕的性能嗎?在開始工作之前我可以採取什麼方法來證明這一點。
如果共識不是索引問題,我還可以研究其他領域嗎?
客戶對更改非常敏感,因此我需要證據才能做出任何更改。
我使用 SQL Sentry 來突出顯示阻塞,插入是顯示的第一個塊,然後是許多其他塊。
這實際上比只有另一個程序阻塞插入器更奇怪。我有一個程序 (51) 被程序 105 阻止。但是,當我檢查程序 105 是關於什麼時,沒有程序 105。
我已經重複了幾次,每次都有不同的程序說它被阻塞了很長一段時間,但“阻塞器”並不真正存在。有誰知道為什麼sys.dm_exec_requests可以說某些東西被阻止了,但是同一個 DMV 說阻止程序實際上並不存在?
發生的情況是,我們在dm_exec_requests中獲得了阻塞會話 id 為 127 的行。但是,儘管dm_exec_sessions中有一個會話,但它表示它正在休眠,並且請求 DMV 中沒有等效的行。
儘管似乎沒有做任何請求,但我不清楚會話如何阻止某些內容 30 分鐘?
對於被阻止的請求,在我今天早上遇到的情況下,它正在等待一個
LCK_M_S
. 有任何想法嗎?
我懷疑這不是“插入需要 7 分鐘”的情況,而是“插入被阻止超過 6 分鐘”的情況。當插入正常執行,然後突然需要很長時間時,可能還有其他原因,SQL Server 不太可能突然被索引過多的大表淹沒。
我在這裡更詳細地處理了這一點,但本質上,您需要在此查詢執行時檢查系統 long。辨識
session_id
(SPID
) 並檢查sys.dm_exec_requests
,blocking_session_id
我認為這很可能是問題所在;之後,檢查wait_type
和last_wait_type
。大多數情況下,對於像這樣的持續時間異常值,其中一列將幫助您找出原因。有時,他們可能沒有活躍的查詢
sys.dm_exec_requests
——正如我在下面的評論中解釋的那樣,如果有人開始一個事務,對一個表做了一些語句,然後沒有送出就走開了,這是可能的。即使他們沒有主動執行查詢,您也可以看到該會話已鎖定哪些對象。DECLARE @SPID INT = <blocking_session_id from your "hung" query>; -- see the command they ran last (might be related, might not) DBCC INPUTBUFFER(@SPID); -- see what that session has locked SELECT s.name, o.name FROM sys.dm_tran_session_transactions AS tst INNER JOIN sys.dm_tran_locks AS tl ON tst.transaction_id = tl.request_owner_id INNER JOIN sys.objects AS o ON tl.resource_associated_entity_id = o.[object_id] INNER JOIN sys.schemas AS s ON o.[schema_id] = s.[schema_id] WHERE tst.session_id = @SPID;