Sql-Server

為什麼同時使用 TRUNCATE 和 DROP?

  • October 18, 2021

在我工作的系統中,有很多使用臨時表的儲存過程和 SQL 腳本。使用這些表後,最好刪除它們。

我的許多同事(幾乎所有人都比我更有經驗)通常這樣做:

TRUNCATE TABLE #mytemp
DROP TABLE #mytemp

DROP TABLE我通常在我的腳本中使用一個。

TRUNCATE在 a之前立即執行 a 有什麼好的理由DROP嗎?

不。

TRUNCATE並且DROP在行為和速度上幾乎相同,因此根本不需要在 aTRUNCATE之前執行正確的操作。DROP


注意:我從 SQL Server 的角度編寫了這個答案,並假設它同樣適用於 Sybase。看來,情況並非完全如此

注意:當我第一次發布這個答案時,還有其他幾個評價很高的答案 - 包括當時接受的答案 - 提出了幾個虛假聲明,例如:TRUNCATE未記錄;TRUNCATE無法回滾;TRUNCATEDROP;快 等等。

既然已經清理了這個執行緒,那麼接下來的反駁似乎與原始問題相切。我把它們留在這裡作為其他人想要揭穿這些神話的參考。


有一些流行的謊言——甚至在有經驗的 DBA 中也很普遍——可能促成了這種TRUNCATE-then-DROP模式。他們是:

  • 誤區TRUNCATE沒有記錄,因此無法回滾。
  • 誤區TRUNCATEDROP

讓我反駁這些謊言。我是從 SQL Server 的角度寫這篇反駁文章的,但我在這裡所說的一切都應該同樣適用於 Sybase。

TRUNCATE 記錄,並且可以回滾。

  • **TRUNCATE是一個記錄的操作,所以可以回滾。**只需將其包裝在事務中即可。
USE [tempdb];
SET NOCOUNT ON;

CREATE TABLE truncate_demo (
   whatever    VARCHAR(10)
);

INSERT INTO truncate_demo (whatever)
VALUES ('log this');

BEGIN TRANSACTION;
   TRUNCATE TABLE truncate_demo;
ROLLBACK TRANSACTION;

SELECT *
FROM truncate_demo;

DROP TABLE truncate_demo;

但是請注意,不適用於 Oracle。儘管由 Oracle 的撤消和重做功能記錄和保護,但TRUNCATE其他 DDL 語句不能由使用者回滾,因為 Oracle在所有 DDL 語句之前和之後立即發出隱式送出。

  • TRUNCATE是最小記錄,而不是完全記錄。那是什麼意思?說你TRUNCATE一張桌子。無需將每個已刪除的行都放入事務日誌中,TRUNCATE只需將它們所在的數據頁標記為未分配。這就是為什麼它這麼快。這也是您無法TRUNCATE使用日誌閱讀器從事務日誌中恢復 -ed 表的行的原因。您會發現所有這些都是對已釋放數據頁的引用。

將此與DELETE. 如果您DELETE將表中的所有行都送出並送出事務,理論上您仍然可以在事務日誌中找到已刪除的行並從那裡恢復它們。那是因為DELETE將每個已刪除的行寫入事務日誌。對於大型表,這將使其比TRUNCATE.

DROP與 TRUNCATE 一樣快。

  • TRUNCATE,DROP是一個最少記錄的操作。 這意味著DROP也可以回滾。這也意味著它的工作方式TRUNCATE. DROP將相應的數據頁標記為未分配,並將表的元數據標記為已刪除,而不是刪除單個行。
  • 因為TRUNCATEDROP工作方式完全相同,它們執行速度一樣快。 **在-ing 表格之前-ing 表格****是沒有意義的。TRUNCATE``DROP**如果您不相信我,請在您的開發實例上執行此展示腳本。

在我的本地機器上,有一個溫暖的記憶體,我得到的結果如下:

table row count: 134,217,728

run#        transaction duration (ms)
     TRUNCATE   TRUNCATE then DROP   DROP
==========================================
01       0               1             4
02       0              39             1
03       0               1             1
04       0               2             1
05       0               1             1
06       0              25             1
07       0               1             1
08       0               1             1
09       0               1             1
10       0              12             1
------------------------------------------
avg      0              8.4           1.3

因此,對於一個 1.34行的表來說DROPTRUNCATE實際上根本不需要任何時間。(在冷記憶體上,第一次或兩次執行大約需要 2-3 秒。)我還認為TRUNCATEthenDROP操作的平均持續時間較長是由於我的本地機器上的負載變化,而不是因為這種組合在某種程度上是神奇的比單個操作差一個數量級。畢竟,它們幾乎完全相同。

如果您對這些操作的日誌記錄成本的更多細節感興趣,Martin 對此有一個簡單的解釋。

引用自:https://dba.stackexchange.com/questions/4163