1. 問題測試
開發人員反映應用程序中一條簡單的delete語句執行報「超時已過時」錯誤。delete語句形式以下:spa
delete * from table_1 where id=@value3d
2. 分析blog
1)驗證delete檢索字段是否有索引索引
首先我想到的是檢索字段 id 列上是否有索引,便是否能很快找到這條待刪除的語句。開發
查看錶的索引列表後,發現id上是存在索引的,並且是彙集索引。it
單獨執行 select * from table_1 where id=@value 走的是彙集索引查找,速度是很是快的table
因此不是由於檢索字段缺失索引致使的select
2)驗證是否存在阻塞引用
接下來猜想是否是發生了阻塞,即delete語句等待其餘會話釋放KEY上的鎖以得到X鎖來執行刪除
使用sys.sysprocesses查詢當前delete會話狀態,發現並未阻塞
3)查看delete語句的預估執行計劃
前兩步驗證完畢後,愈加以爲有點無從下手的感受。拋下本身所謂的經驗,先看下delete語句執行計劃吧
由於語句執行超時,不能查看真正的執行計劃,因此查看估計的執行計劃來分析問題。
以在AdventureWorks2012測試刪除爲例
執行delete from Person.Person where BusinessEntityID=6,執行計劃部分截圖爲:
3. 結論
從執行計劃中,發現了問題緣由:
刪除數據的表被其餘表所引用,SQLServer在刪除被引用表數據時,會檢查引用表是否存在引用值記錄,以保證數據的參照完整性。
而目前引用表在外鍵字段上沒有索引,致使使用索引掃描來查找,而且引用表記錄數在百萬以上,致使刪除超時
4. 處理
在引用表的外鍵字段上增長非彙集索引
5. 思考
1)應用程序的物理刪除數據是否合理及必須呢?是否能夠經過增長刪除標記或者單據狀態之類,來實現邏輯刪除呢?
2)引用表中字段的外鍵是否必須創建呢?看了一些應用系統,如用友、金蝶的系統,表中的外鍵字段不多。外鍵字段過多對插入刪除的速度會有必定的影響。
3)若是創建了外鍵約束的話,引用表的外鍵字段和被引用表的主鍵字段應該最好要創建索引
若有不對的地方,歡迎拍磚,謝謝!O(∩_∩)O