由delete導致的超時已過期問題


 

1. 問題

  開發人員反映應用程序中一條簡單的delete語句執行報“超時已過期”錯誤。delete語句形式如下:

  delete * from table_1 where id=@value

2. 分析

  1)驗證delete檢索字段是否有索引

  首先我想到的是檢索字段 id 列上是否有索引,即是否能很快找到這條待刪除的語句。

  查看表的索引列表后,發現id上是存在索引的,而且是聚集索引。

  單獨執行 select * from table_1 where id=@value 走的是聚集索引查找,速度是非常快的

  所以不是因為檢索字段缺失索引導致的

  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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM