SQLSERVER 的 truncate 和 delete 有區別嗎?

来源:https://www.cnblogs.com/huangxincheng/archive/2023/02/09/17104847.html
-Advertisement-
Play Games

一:背景 1. 講故事 在面試中我相信有很多朋友會被問到 truncate 和 delete 有什麼區別 ,這是一個很有意思的話題,本篇我就試著來回答一下,如果下次大家遇到這類問題,我的答案應該可以幫你成功度過吧。 二:區別詳解 1. 思考 從巨集觀角度來說, delete 是 DML 語句, tru ...


一:背景

1. 講故事

在面試中我相信有很多朋友會被問到 truncate 和 delete 有什麼區別 ,這是一個很有意思的話題,本篇我就試著來回答一下,如果下次大家遇到這類問題,我的答案應該可以幫你成功度過吧。

二:區別詳解

1. 思考

從巨集觀角度來說, delete 是 DML 語句, truncate 是 DDL 語句,這些對資料庫產生破壞類的語句肯定是要被 sqlserver 跟蹤的,言外之意就是在某些場景下可以被回滾的,既然可以被 回滾,那自然就會產生 事務日誌,所以從 事務日誌 的角度入手會是一個好的辦法。

為了方便測試,還是用上一篇的 post 表,創建好之後插入10條記錄,參考sql如下:


DROP TABLE dbo.post;
CREATE TABLE post (id INT IDENTITY, content CHAR(1000) DEFAULT 'aaaaaa')

INSERT post DEFAULT VALUES 
GO 10

有了數據之後就可以通過 fn_dblog 函數從 MyTestDB.ldf 中提取事務日誌來觀察 delete 和 truncate 日誌的不同點。

2. 觀察 delete 的事務日誌。

為了觀察 delete 產生的日誌,這裡用 @max_lsn 記錄一下起始點,參考sql如下:


DECLARE @max_lsn VARCHAR(100)
SELECT @max_lsn=[Current LSN] FROM fn_dblog(NULL,NULL)
DELETE FROM post;
SELECT * FROM fn_dblog(NULL,NULL) WHERE [Current LSN] >@max_lsn

從事務日誌看, delete 主要做了兩件事情。

  • 10 行 delete 記錄刪除

這裡就有一個好奇的地方了,sqlserver 是如何執行刪除操作的呢?要回答這個問題需要到數據頁上找答案,參考sql如下:


DBCC IND(MyTestDB,post,-1)
DBCC PAGE(MyTestDB,1,240,2)

從圖中可以得到如下兩點信息, 至少在堆表下 delete 操作並沒有刪除 Page,第二個是 delete 記錄刪除只是將 slot 的指針 抹0

有些朋友可能要問,為什麼還有對 PFS 的操作呢?很簡單它就是用來記錄當前頁面的 占用空間比率 的,可以看下我的上一篇文章。

3. 觀察 truncate 的事務日誌。

delete 原理搞清楚之後,接下來看下 truncate 做了什麼?參考sql 如下:


DROP TABLE dbo.post;
CREATE TABLE post (id INT IDENTITY, content CHAR(1000) DEFAULT 'aaaaaa')

INSERT post DEFAULT VALUES 
GO 10

DECLARE @max_lsn VARCHAR(100)
SELECT @max_lsn=[Current LSN] FROM fn_dblog(NULL,NULL)
TRUNCATE TABLE dbo.post
SELECT [Current LSN],Operation,Context,AllocUnitName FROM fn_dblog(NULL,NULL) WHERE [Current LSN] >@max_lsn

從圖中可以看到,truncate 主要是對 IAM, PFS, GAM 三個空間管理數據頁做了修改,並沒有涉及到 PAGE 頁,那就有一個疑問了,我的PAGE頁還在嗎?可以用 DBCC IND 看下。

我去,truncate 操作居然把我的 PAGE 頁給弄丟了,它是怎麼實現的呢? 要想找到答案,大家可以想一想, truncate 是一個 DDL 語句,為了快速釋放表數據,它乾脆把 postpage 的關係給切斷了,如果大家有點懵,畫個圖大概就是下麵這樣。

為了驗證這個結論,可以用 DBCC PAGE 直接導出 240 號數據頁,觀察下是不是表中的數據,不過遺憾的是,這個數據頁已不歸屬 post 表了。。。

接下來又得回答另外一個問題,sqlserver 是如何切斷的? 這裡就需要理解 GAM 空間管理機制。

三:GAM 空間管理

1. 基本原理

GAM 是用來跟蹤 區分配 狀態的數據頁,它是用一個 bit 位跟蹤一個 , 在資料庫中一個區表示 連續的8個數據頁,在 GAM 數據頁中,用 1 表示可分配的初始狀態,用 0 表示已分配狀態,可能大家有點懵,我再畫個簡圖吧。

為了讓大家眼見為實,還是用 post 給大家做個演示。


DROP TABLE dbo.post;
CREATE TABLE post (id INT IDENTITY, content CHAR(1000) DEFAULT 'aaaaaa')
INSERT post DEFAULT VALUES 
GO 10

DBCC TRACEON(3604)
DBCC IND(MyTestDB,post,-1)

從圖中可以看到,post 表分配的數據頁是 240241 號,對應的區號就是 240/8 + 1 = 31,因為 GAM 是用 1bit 來跟蹤一個區,所以理論上 GAM 頁面偏移 31bit 的位置就標記了該區的分配情況。

這麼說可能大家又有點懵,我準備用 windbg 來演示一下,首先大家要記住 GAM 是 mdf 文件中的第三個頁面,用 2 表示, 前兩個分別是 文件頭 和 PFS 頁,關於頁面的首地址可以用 DBCC PAGE(MyTestDB,1,2,2) 導出來。


0:078> dp 00000009009F8000 +0x60
00000009`009f8060  00000000`005e0000 00000000`00000000
00000009`009f8070  00000000`00000000 00000000`00000000
00000009`009f8080  00000000`00000000 00000000`00000000
00000009`009f8090  00000000`00000000 00000000`00000000
00000009`009f80a0  00000000`00000000 00000000`00000000
00000009`009f80b0  00000000`00000000 00000000`00000000
00000009`009f80c0  d0180000`00001f38 ffffffff`ffffffd1
00000009`009f80d0  ffffffff`ffffffff ffffffff`ffffffff

從輸出內容看,那個 0x1f38 就是 bitmap 數組的長度,後面就是 bit 的占用情況,因為在 31 bit 上,我們觀察一個 int 就好了,輸出如下:

從圖中可以看到,全部都是 0 也就說明當前都是分配狀態,如果是 1 表示未分配,接下來把 post 給 truncate 掉再次觀察 GAM 頁。


TRUNCATE TABLE dbo.post;
DBCC PAGE(MyTestDB,1,2,2)

輸出如下:


0:117> dp 00000009009F8000+0x60
00000009`009f8060  00000000`005e0000 00000000`00000000
00000009`009f8070  00000000`00000000 00000000`00000000
00000009`009f8080  00000000`00000000 00000000`00000000
00000009`009f8090  00000000`00000000 00000000`00000000
00000009`009f80a0  00000000`00000000 00000000`00000000
00000009`009f80b0  00000000`00000000 00000000`00000000
00000009`009f80c0  d0184000`00001f38 ffffffff`ffffffd1
00000009`009f80d0  ffffffff`ffffffff ffffffff`ffffffff

對比之後會發現由原來的 000000001f38 變成了 400000001f38,可以用 .format 來格式化下。

從圖中看 31bit 跟蹤的第 31 號區被回收了,也就驗證了真的切斷了聯繫。

同樣的道理 PFS 偏移的 0n240 位置跟蹤的這個頁面也是被釋放狀態。

四:總結

總的來說,delete 操作是將數據頁中的每個 slot 指針一條一條的擦掉,每次擦除都會產生一條事務日誌,所以對海量數據進行 delete 會產生海量的事務日誌,導致你的 日誌文件 暴增。而 truncate 是直接切斷 post 和 page 的聯繫,只需要修改幾個空間管理頁的 bit 位即可。

最後的建議是如果要清空表數據,建議用 truncate table


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、Linux文件和目錄簡單操作{#一-linux文件和目錄簡單操作} 1.1 查看文件 ls 查看當前目錄下的文件 如: -a 顯示所有文件及目錄 (ls內定將文件名或目錄名稱開頭為"."的視為隱藏檔,不會列出) -l 除文件名稱外,亦將文件型態、許可權、擁有者、文件大小等資訊詳細列出 -r 將文件 ...
  • ​ 一、前言 萬物皆有源頭,大家學習單片機的源頭操作就是通過GPIO口點燈,GPIO作為STM32最基礎的外設,也是大家最先接觸的外設。當然,看似基礎的GPIO,不僅僅是簡單的設置好IO口,讓燈亮起就一了百了,瞭解清楚GPIO的使用特性,根本原理、運行機制對我們在涉及到GPIO的相關設計操作上會應用 ...
  • 問題描述 啟動腳本第一行提示line 1: #!/bin/sh: No such file or directory 看著都難受,有強迫症必須修複它 log [weblogic@hz-dzswj-sc-x sh]$ ./start_bszm-web.sh ./start_bszm-web.sh: l ...
  • FCoE FCoE是一種融合網路技術,其目的是將FC幀封裝到乙太網幀中,實現乙太網鏈路與光纖鏈路通信的功能。 SAN一般指存儲區域網路,FC SAN 有光纖組網,IP SAN由乙太網電纜組網。 LAN一般指區域網,乙太網組網。 通常情況下業務前端面向普通用戶都是採用乙太網提供服務,在業務的後端由於龐 ...
  • 1.美國FCC認證新要求 繼2022年11月25日FCC發佈了FCC 22-84法規禁止授權被認為對美國國家安全構成威脅的通信和視頻監控設備後,2023年1月24日FCC又發佈了KDB 986446 D01 Covered Equipment v01 guidance,明確要求TCB不得向被製裁清單 ...
  • 作者:vivo 互聯網運維團隊- Hou Dengfeng 本文主要介紹使用shell實現一個簡易的Docker。 一、目的 在初接觸Docker的時候,我們必須要瞭解的幾個概念就是Cgroup、Namespace、RootFs,如果本身對虛擬化的發展沒有深入的瞭解,那麼很難對這幾個概念有深入的理解 ...
  • MySQL基礎查詢練習 前提準備 使用ddl語句創建資料庫 student表格: create table student( id int PRIMARY KEY COMMENT 'id主鍵', `name` varchar(20) COMMENT '名稱', gender TINYINT(2) C ...
  • 表: 查詢語句 -- 查詢姓“猴”的學生名單 SELECT * from student WHERE 姓名 like "猴%"; -- 查詢姓“孟”老師的個數 SELECT COUNT(教師姓名) FROM teacher WHERE 教師姓名 LIKE "孟%"; -- 查詢課程編號為“0002” ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...