轉載博客:http://blog.csdn.net/dba_huangzj/article/details/7913068數據庫
通常在刪除表數據時候,一般會有執行兩個SQL語句:delete和truncate,有條件的刪除咱們平時都會用delete,而若是所有刪除,那咱們一般都會選擇truncate,由於這個你們都知道,delete會一條條刪除,全刪除條件下,truncate比delete速度快不少,可是究竟是怎麼樣的,這個就不太清楚測試
那咱們今天就來研究下二者具體的區別spa
樣例1:測試delete.net
首先建立3個各有1000行數據的表,Fact_Sale_1,Fact_Sale_2,Fact_Sale_3,其中,Fact_Sale_2建立一個彙集索引,Fact_Sale_3建立一個非彙集索引,以下:日誌
--直接將數據插入表,不是用任何索引 SELECT TOP 1000 * INTO [Test].[dbo].Fact_Sale_1 FROM [DW_HQ].[dbo].[Fact_Sale] AS a WITH(NOLOCK) GO SELECT TOP 1000 * INTO [dbo].Fact_Sale_2 FROM [DW_HQ].[dbo].[Fact_Sale] AS a WITH(NOLOCK) GO --建立彙集索引 CREATE CLUSTERED INDEX CLUS_IX_Fact_Sale_2_Datekey ON [dbo].[Fact_Sale_2]([Datekey]) GO SELECT TOP 1000 * INTO [dbo].Fact_Sale_3 FROM [DW_HQ].[dbo].[Fact_Sale] AS a WITH(NOLOCK) GO --建立非彙集索引 CREATE NONCLUSTERED INDEX NONCLUS_IX_Fact_Sale_3_Datekey ON [dbo].[Fact_Sale_3]([Datekey]) GO
而後咱們查看一下各個表的索引狀況code
EXEC [sys].[sp_helpindex] @objname = N'Fact_Sale_1' -- nvarchar(776) GO
/*結果
對象 'Fact_Sale_1' 沒有任何索引,或者您沒有所需的權限。*/
EXEC [sys].[sp_helpindex] @objname = N'Fact_Sale_2' -- nvarchar(776)
GO
/*結果
index_name index_description index_keys
CLUS_IX_Fact_Sale_2_Datekey clustered located on PRIMARY Datekey*/對象
EXEC [sys].[sp_helpindex] @objname = N'Fact_Sale_3' -- nvarchar(776)
GO
/*
index_name index_description index_keys
NONCLUS_IX_Fact_Sale_3_Datekey nonclustered located on PRIMARY Datekey*/blog
接着咱們使用delete命令刪除這個三個表的數據索引
DELETE FROM [dbo].[Fact_Sale_1] GO DELETE FROM [dbo].[Fact_Sale_2] GO DELETE FROM [dbo].[Fact_Sale_3] GO
使用DBCC SHOWCONTIG()查看咱們刪除後的數據表存儲狀況事務
/* DBCC SHOWCONTIG 正在掃描 'Fact_Sale_1' 表... 表: 'Fact_Sale_1' (2105058535);索引 ID: 0,數據庫 ID: 34 已執行 TABLE 級別的掃描。 - 掃描頁數................................: 30 - 掃描區數..............................: 5 - 區切換次數..............................: 4 - 每一個區的平均頁數........................: 6.0 - 掃描密度 [最佳計數:實際計數].......: 80.00% [4:5] - 區掃描碎片 ..................: 20.00% - 每頁的平都可用字節數.....................: 8029.3 - 平均頁密度(滿).....................: 0.80% DBCC 執行完畢。若是 DBCC 輸出了錯誤信息,請與系統管理員聯繫。 */
/* DBCC SHOWCONTIG 正在掃描 'Fact_Sale_2' 表... 表: 'Fact_Sale_2' (2121058592);索引 ID: 1,數據庫 ID: 34 已執行 TABLE 級別的掃描。 - 掃描頁數................................: 1 - 掃描區數..............................: 1 - 區切換次數..............................: 0 - 每一個區的平均頁數........................: 1.0 - 掃描密度 [最佳計數:實際計數].......: 100.00% [1:1] - 邏輯掃描碎片 ..................: 0.00% - 區掃描碎片 ..................: 0.00% - 每頁的平都可用字節數.....................: 7865.0 - 平均頁密度(滿).....................: 2.83% DBCC 執行完畢。若是 DBCC 輸出了錯誤信息,請與系統管理員聯繫。 */
/* DBCC SHOWCONTIG 正在掃描 'Fact_Sale_3' 表... 表: 'Fact_Sale_3' (2137058649);索引 ID: 0,數據庫 ID: 34 已執行 TABLE 級別的掃描。 - 掃描頁數................................: 30 - 掃描區數..............................: 5 - 區切換次數..............................: 4 - 每一個區的平均頁數........................: 6.0 - 掃描密度 [最佳計數:實際計數].......: 80.00% [4:5] - 區掃描碎片 ..................: 20.00% - 每頁的平都可用字節數.....................: 8029.3 - 平均頁密度(滿).....................: 0.80% DBCC 執行完畢。若是 DBCC 輸出了錯誤信息,請與系統管理員聯繫。 */
能夠看到,沒有彙集索引的表delete以後分區和頁數都是一致的都是30和5,而有彙集索引的表只有1個分區和1個頁數,而且這些空間都是空的,沒有彙集索引,刪除後就會形成咱們平時刪除數據後空間上形成極大的浪費。
樣例2:測試truncate
一樣建立上述3個表,同樣的建立索引和非彙集索引,而後咱們使用truncate命令刪除全部的數據,在使用DBCC SHOWCONTIG()來查看數據表存儲狀況,以下:
/* DBCC SHOWCONTIG 正在掃描 'Fact_Sale_1' 表... 表: 'Fact_Sale_1' (21575115);索引 ID: 0,數據庫 ID: 34 已執行 TABLE 級別的掃描。 - 掃描頁數................................: 0 - 掃描區數..............................: 0 - 區切換次數..............................: 0 - 每一個區的平均頁數........................: 0.0 - 掃描密度 [最佳計數:實際計數].......: 100.00% [0:0] - 區掃描碎片 ..................: 0.00% - 每頁的平都可用字節數.....................: 0.0 - 平均頁密度(滿).....................: 0.00% DBCC 執行完畢。若是 DBCC 輸出了錯誤信息,請與系統管理員聯繫。 */
/* DBCC SHOWCONTIG 正在掃描 'Fact_Sale_2' 表... 表: 'Fact_Sale_2' (37575172);索引 ID: 1,數據庫 ID: 34 已執行 TABLE 級別的掃描。 - 掃描頁數................................: 0 - 掃描區數..............................: 0 - 區切換次數..............................: 0 - 每一個區的平均頁數........................: 0.0 - 掃描密度 [最佳計數:實際計數].......: 100.00% [0:0] - 邏輯掃描碎片 ..................: 0.00% - 區掃描碎片 ..................: 0.00% - 每頁的平都可用字節數.....................: 0.0 - 平均頁密度(滿).....................: 0.00% DBCC 執行完畢。若是 DBCC 輸出了錯誤信息,請與系統管理員聯繫。 */
/* DBCC SHOWCONTIG 正在掃描 'Fact_Sale_3' 表... 表: 'Fact_Sale_3' (53575229);索引 ID: 0,數據庫 ID: 34 已執行 TABLE 級別的掃描。 - 掃描頁數................................: 0 - 掃描區數..............................: 0 - 區切換次數..............................: 0 - 每一個區的平均頁數........................: 0.0 - 掃描密度 [最佳計數:實際計數].......: 100.00% [0:0] - 區掃描碎片 ..................: 0.00% - 每頁的平都可用字節數.....................: 0.0 - 平均頁密度(滿).....................: 0.00% DBCC 執行完畢。若是 DBCC 輸出了錯誤信息,請與系統管理員聯繫。 */
能夠看到,3個表的分區、頁數都爲0,空間也爲0,。
所以:
一、truncate比delete所用的事務日誌空間更少: delete是一行一行操做,而且把記錄都存進日誌文件(不管任何恢復模式,都會記錄日誌)。而truncate操做,是對一個頁操做,在日誌中,僅僅記錄釋放頁面的這個動做,而不記錄每一行。 二、truncate比delete使用鎖一般較少: delete因爲是一行一行刪除,因此須要對處理的行進行加鎖,並且是行鎖。truncate操做因爲是對頁操做,因此只須要申請頁鎖或者表鎖。 三、truncate對錶中的全部頁都清空: 執行delete後,表仍是會有空頁,可是truncate則會所有清除。可是truncate會保留表結構、列、約束、索引等。 爲了更好地刪除空間,可使用如下方法: 一、在表中建立彙集索引 二、若是全部數據已經不要,那使用truncate而不是delete 另外,對於delete操做而留下的空間,會在插入時重用。若是以爲這些空間存在很差,那麼能夠重建(建立)彙集索引來釋放空間。