博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Delete和Truncate的区别
阅读量:6825 次
发布时间:2019-06-26

本文共 2761 字,大约阅读时间需要 9 分钟。

原文:

 

一般对于没有用的数据,都会经行删除,而删除通常使用的是DELETETRUNCATE命令。对于有条件地删除,基本上就会使用DELETE,当然还是没有绝对,用TRUNCATE也可以实现,只要把【不需要】删除的数据插入新表,然后truncate源表,再把数据导回来或者直接重命名新表就可以了。

下面例子主要比较全表删除的情况下DELETE TRUNCATE 之间的差异:

 

首先,先创建测试用例:本例使用AdventureWorks数据库。先创建3个表:

--堆,即没有聚集索引SELECT * INTO Sales.SalesOrderDetail_D FROM  Sales.SalesOrderDetail--有聚集索引SELECT * INTO Sales.SalesOrderDetail_J FROM  Sales.SalesOrderDetail CREATE CLUSTERED INDEX Clustered_SalesOrderDetail_J ON Sales.SalesOrderDetail_J (SalesOrderID,SalesOrderDetailID)GO--没有聚集索引,但有非聚集索引SELECT * INTO Sales.SalesOrderDetail_F FROM  Sales.SalesOrderDetailCREATE NONCLUSTERED INDEX Nonclustered_SalesOrderDetail_F ON Sales.SalesOrderDetail_F (SalesOrderID,SalesOrderDetailID)GO

 

查看一下各个表的索引情况:

sp_helpindex '[Sales].SalesOrderDetail_D';GO

 

结果:

 

sp_helpindex '[Sales].SalesOrderDetail_J';GO

 

结果:

 

sp_helpindex '[Sales].SalesOrderDetail_F'

 

结果:

 

然后,用DELETE对三个表进行清空操作:

DELETE TABLE [Sales].SalesOrderDetail_DGODELETE TABLE [Sales].SalesOrderDetail_JgoDELETE TABLE [Sales].SalesOrderDetail_F

 

使用DBCC SHOWCONTIG命令来查看数据分布情况:

DBCC SHOWCONTIG( '[Sales].SalesOrderDetail_D')GODBCC SHOWCONTIG('[Sales].SalesOrderDetail_J')goDBCC SHOWCONTIG('[Sales].SalesOrderDetail_F')

 

结果如下:

从上图可以看出,堆表(即没有聚集索引的表)扫描出82个页和11个区,由于已经删除属于,所以这些都是空的。而有聚集索引的表,只有1个页和1个区。有非聚集索引的表,也有66个页和9个区。

可以看到,没有聚集索引的表删除数据后还遗留了不少空间。

 

 

下面来看看TRUNCATE操作:

同样,先创建表,使用上面的建表语句创建同样的表,以保证对比一致性:

DROP TABLE Sales.SalesOrderDetail_DGODROP TABLE Sales.SalesOrderDetail_JGODROP TABLE Sales.SalesOrderDetail_FGO --堆,即没有聚集索引SELECT * INTO Sales.SalesOrderDetail_D FROM  Sales.SalesOrderDetail --有聚集索引SELECT * INTO Sales.SalesOrderDetail_J FROM  Sales.SalesOrderDetail  CREATE CLUSTERED INDEX Clustered_SalesOrderDetail_J ON Sales.SalesOrderDetail_J(SalesOrderID,SalesOrderDetailID)GO--没有聚集索引,但有非聚集索引SELECT * INTO Sales.SalesOrderDetail_F FROM  Sales.SalesOrderDetail CREATE NONCLUSTERED INDEX Nonclustered_SalesOrderDetail_F ON Sales.SalesOrderDetail_F(SalesOrderID,SalesOrderDetailID)GO

 

然后查看相关索引:

sp_helpindex '[Sales].SalesOrderDetail_D';GO

结果:

 

sp_helpindex '[Sales].SalesOrderDetail_J';go

结果:

 

sp_helpindex '[Sales].SalesOrderDetail_F'

结果:

 

现在进行清空操作:

TRUNCATE TABLE [Sales].SalesOrderDetail_DGOTRUNCATE TABLE [Sales].SalesOrderDetail_JgoTRUNCATE TABLE [Sales].SalesOrderDetail_F

 

再检查数据分布情况:

可以看到,3个表都已经没有页和区了。

 

通过上面的对比,可以得出以下结论:

1、  TruncateDelete所用的事务日志空间更少:

DELETE 是一行一行操作,并且把记录都存进日志文件(说明一下,无论任何恢复模式,都会记录日志)。而TRUNCATE操作,是对一个页操作,在日志中,仅仅记录释放页面的这个动作,而不记录每一行。

2、  TruncateDelete使用锁通常较少:

DELETE由于是一行一行删除,所以需要对处理的行进行加锁,而且是行锁。TRUNCATE操作由于是对页操作,所以只需要申请页锁或者表锁。

3、  TRUNCATE对表中的所有页都清空:

执行DELETE后,表还是会有空页,但是TRUNCATE则会全部清除。但是TRUNCATE会保留表结构、列、约束、索引等。而DELETE之后,会哦他能够过后台清除空页。

 

为了更好地删除空间,可以使用以下方法:

1)、在表中创建聚集索引

2)、如果所有数据已经不要,那使用TRUNCATE 而不是DELETE,删除后DROP TABLE

 

另外,对于由于DELETE操作而留下的空间,会在插入时重用。如果觉得这些空间存在不好,那么可以重建/创建聚集索引来释放空间。

转载地址:http://youkl.baihongyu.com/

你可能感兴趣的文章
RichTextBox.MouseWheel事件控制父控件Panel的内容滚动
查看>>
php程序在浏览器哪里判断,一个判断PHP程序是否被同时在不同浏览器上执行的问题...
查看>>
php 获取5分钟前,php时间轴开发,即显示为“刚刚”、“5分钟前”、“昨天12:10...
查看>>
php ob_end_clean(),ob_end_clean(): failed to delete buffer-ThinkPHP 5.1.23
查看>>
谈谈编程修养
查看>>
合伙创业的经历
查看>>
Powershell管理系列(四)Lync server 2013 批量启用语音及分配分机号
查看>>
在Mac上安装mysql数据库记录
查看>>
脚本助手之echo命令显示带指定颜色的字!
查看>>
增加智能感知的RichTextBox扩展控件(WPF)
查看>>
大家一起来学习一下面向对象的三层架构吧!今天我来说说Entity有时也叫MODEL实体层!...
查看>>
个人管理:发掘自己的性格优势
查看>>
Rails性能优化简明指南 (转载)
查看>>
关于D3D11,你必须了解的几件事情(一)
查看>>
AutoResetEvent和ManualResetEvent的使用与区别
查看>>
shell中的fork、source和exec总结(包括环境变量)
查看>>
《Effective C#》读书笔记——条目4:使用Conditional特性而不是#if条件编译<C#语言习惯>...
查看>>
浅谈异常与恋爱
查看>>
分享:http-watcher更新,改进对动态web程序的支持
查看>>
设计模式---->经典设计模式一览
查看>>