DELETE和TRUNCATE之間的區別
摘抄自《SQLSERVER企業級平台管理實踐》
與delete相比,truncate具有以下優點:
1、所用的事務日志空間較少
delete語句每次刪除一行,並在事務日志中為所刪除的每行記錄一個項。truncate table通過釋放用於存儲表數據的數據頁來刪除數據,並且在事務
日志中只記錄頁釋放這個動作,而不記錄每一行
2、使用的鎖通常較少
當使用行鎖執行delete語句時,將鎖定表中各行以便刪除。truncate table始終鎖定表和頁,而不是鎖定各行。
3、表中將毫無例外地留下任何頁
執行delete語句后,表依然會包含空頁。例如,必須至少使用一個排他表鎖(LCK_M_X),才能釋放堆中的空頁。如果執行刪除操作
時沒有使用表鎖,表(堆)中將包含許多空頁。對於索引,刪除操作會留下一些空頁,盡管這些頁會通過后台清除進程迅速釋放。
truncate table刪除表中的所有行,但表結構以及列、約束、索引等保持不變。若要刪除表定義以及數據,請使用drop table語句
-------------------------------------------------華麗的分割線-----------------------------------------------------------
為了更及時地刪除數據,釋放空間,可以采用的方法有:
(1)在表格上建立聚集索引
(2)如果所有數據都不要了,要使用truncate table而不是delete
(3)如果表格本身不要了,就直接drop table
----------------------------------------------華麗的分割線------------------------------------------------------
delete了的數據,SQLSERVER卻沒有完全釋放空間,這不是空間泄漏嗎?久而久之,我的數據庫里會不會充斥着這些“沒用”的頁面,
把我的空間都浪費掉了?這倒不必擔心,雖然這些頁面沒有被釋放掉,但當表格里插入新的數據時,這些頁面是會被重新使用的。
所以這些頁面並沒有被“泄漏”掉,會留給SQLSERVER重用
如果真的看着這些頁面礙事,而表格又不能整個刪除掉,處理起來有時候有點費事。如果表格有聚集索引,可以重建一下索引能釋放掉
這些頁面,還是挺簡單的。但是如果沒有,可能就要重建一張新表,把數據從舊表里倒過去,然后再刪除舊表,釋放空間;或者
在這張表上建一個聚集索引。這樣有點折騰。所以表沒用了,就直接刪掉他;如果表還有用,那這些頁面將來再有新數據插入時,
還會被利用上。一般沒必要一定要逼着SQLSERVER把他們釋放出來。
--------------------------------------------華麗的分割線---------------------------------------------------------
有朋友說truncate table會使用鬼影記錄,但是根據我寫的文章里說到:鬼影記錄只存在於有聚集索引的表和使用快照隔離級別的堆表
然后我測試了一下,確實沒有鬼影記錄,根據上面說的truncate table與delete的比較,其實truncate table沒有必要使用鬼影記錄
至於為什麽大家需要看一下我寫的鬼影記錄的文章作對比
我實驗的時候使用了我的一篇隨筆,修改了隨筆里的一些sql語句,來模擬實驗環境
我的實驗就是修改《關於鬼影記錄的翻譯一》里的那個sql語句來做的
1 USE [GPOSDB] 2 GO 3 CREATE TABLE t1 ( c1 CHAR(10) ) 4 CREATE CLUSTERED INDEX t1c1 ON t1 (c1) 5 GO 6 BEGIN TRAN PaulsTran 7 INSERT INTO t1 VALUES ( 'PAUL' ) 8 INSERT INTO t1 VALUES ( 'KIMBERLY' ) 9 GO 10 TRUNCATE TABLE t1 --改為truncate table 你會發現在事務日志里查找不出鬼影記錄 11 GO 12 13 DBCC IND ('GPOSDB', 't1', 1); 14 GO 15 ----------------------- 16 --補充一下:DBCC IND 里的page type列 17 PageType 18 Page type: 19 1 = data page, 20 2 = index page, 21 3 = LOB_MIXED_PAGE, 22 4 = LOB_TREE_PAGE, 23 10 = IAM page 24 25 ---------------------- 26 DBCC TRACEON (3604); 27 GO 28 DBCC PAGE ('gposdb', 1, 482, 3); 29 DBCC PAGE ('gposdb', 1, 482, 2);
如果有不對的地方,歡迎大家一起來拍磚o(∩_∩)o