【转载】SQL SERVER-Delete和Truncate的区别
转载博客:http://blog.csdn.net/dba_huangzj/article/details/7913068
背景
一般在删除表数据时候,通常会有执行两个SQL语句:delete和truncate,有条件的删除我们平时都会用delete,而如果全部删除,那我们通常都会选择truncate,因为这个大家都知道,delete会一条条删除,全删除条件下,truncate比delete速度快很多,但是到底是怎么样的,这个就不太清楚
那我们今天就来研究下两者具体的区别
操作
样例1:测试delete
首先创建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
然后我们查看一下各个表的索引情况
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*/
接着我们使用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,。
因此:
1、truncate比delete所用的事务日志空间更少:
delete是一行一行操作,并且把记录都存进日志文件(无论任何恢复模式,都会记录日志)。而truncate操作,是对一个页操作,在日志中,仅仅记录释放页面的这个动作,而不记录每一行。
2、truncate比delete使用锁通常较少:
delete由于是一行一行删除,所以需要对处理的行进行加锁,而且是行锁。truncate操作由于是对页操作,所以只需要申请页锁或者表锁。
3、truncate对表中的所有页都清空: 执行delete后,表还是会有空页,但是truncate则会全部清除。但是truncate会保留表结构、列、约束、索引等。
为了更好地删除空间,可以使用以下方法:
1、在表中创建聚集索引
2、如果所有数据已经不要,那使用truncate而不是delete
另外,对于delete操作而留下的空间,会在插入时重用。如果觉得这些空间存在不好,那么可以重建(创建)聚集索引来释放空间。
【转载】SQL SERVER-Delete和Truncate的区别的更多相关文章
- SQL Server delete、truncate、drop
在T-SQL中这三个命令符,相信很多朋友都不会陌生的,我自己在工作也会常常使用到它们,虽然我们清除的知道用这三个命令符可以达到怎样的预期效果. 但是却很少深入的去了解它们,知道它们有什么区别,又各有什 ...
- sql server 维护计划与作业关系区别
sql server 维护计划与作业关系区别 对于二者的区别,你可以把维护计划看作是针对数据库进行维护的作业模板.自定义作业具有更广泛的用途,当然,也具有更复杂的操作.所以,如果 仅仅是做个数据库优化 ...
- oracle中drop、delete和truncate的区别
oracle中drop.delete和truncate的区别 oracle中可以使用drop.delete和truncate三个命令来删除数据库中的表,网上有许多文章和教程专门讲解了它们之间的异同,我 ...
- Delete和Truncate的区别
原文:Delete和Truncate的区别 一般对于没有用的数据,都会经行删除,而删除通常使用的是DELETE和TRUNCATE命令.对于有条件地删除,基本上就会使用DELETE,当然还是没有绝对,用 ...
- 数据库 --> SQL Server 和 Oracle 以及 MySQL 区别
SQL Server 和 Oracle 以及 MySQL 区别 三者是目前市场占有率最高(依安装量而非收入)的关系数据库,而且很有代表性.排行第四的DB2(属IBM公司),与Oracle的定位和架构非 ...
- SQL Server char,varchar,nchar,nvarchar区别
SQL Server char,varchar,nchar,nvarchar区别 (1) 定义: char: 固定长度,存储ANSI字符,不足的补英文半角空格. nchar: 固 ...
- 数据库中drop、delete与truncate的区别
数据库中drop.delete与truncate的区别 drop直接删掉表: truncate删除表中数据,再插入时自增长id又从1开始 :delete删除表中数据,可以加where字句. (1) D ...
- SQL Server,MySQL,Oracle三者的区别
SQL Server,MySQL,Oracle三者的区别 2016-10-14 转自:SQL Server,MySQL,Oracle三者的区别 目录 1 Oracle.Sql Server.MySql ...
- sql server几种Join的区别测试方法与union表的合并
/* sql server几种Join的区别测试方法 主要来介绍下Inner Join , Full Out Join , Cross Join , Left Join , Right Join的区别 ...
- SQL Server中DELETE和TRUNCATE的区别
DELETE和TRUNCATE语句之间的区别是求职面试中最常见的问题之一.这两条语句都可以从表中删除数据.然而,也有不同之处. 本文将重点讨论这些差异,并通过实例加以说明. TRUNCATE DEL ...
随机推荐
- Java-数据结构之二叉树练习
本来这个随笔应该在4月17号就应该发出来的.不巧的是,那天晚上收到了offer,然后接下去两天为入职到处跑,20号入职后一直忙,直到最近几天才有时间看看书.然而20多天前就看完的了二叉树,然后17号那 ...
- centos使用--开机启动
centos6.8 1.利用 chkconfig 来配置启动级别 在CentOS或者RedHat其他系统下,如果是后面安装的服务,如httpd.mysqld.postfix等,安装后系统默认不会自动启 ...
- Erlang中常用的类型转换[转]
转自: http://blog.sina.com.cn/s/blog_53a5047b01018yqv.html 例子 结果 atom_to_list(hello). "hello" ...
- Android通过用代码画虚线椭圆边框背景来学习一下shape的用法
在Android程序开发中,我们经常会去用到Shape这个东西去定义各种各样的形状,shape可以绘制矩形环形以及椭圆,所以只需要用椭圆即可,在使用的时候将控件比如imageview或textview ...
- 《Cracking the Coding Interview》——第3章:栈和队列——题目2
2014-03-18 05:08 题目:实现一个栈,除了能进行push和pop之外,还能在O(1)时间内返回栈中最小的元素. 解法:用另一个“最小栈”存放最小的元素,每当有不小于当前最小值的元素进栈时 ...
- 自动化测试(三)如何用python写一个函数,这个函数的功能是,传入一个数字,产生N条邮箱,产生的邮箱不能重复。
写一个函数,这个函数的功能是,传入一个数字,产生N条邮箱,产生的邮箱不能重复.邮箱前面的长度是6-12之间,产生的邮箱必须包含大写字母.小写字母.数字和特殊字符 和上一期一样 代码中间有段比较混沌 有 ...
- HDU 4346 The Beautiful Road ( 反向考虑 思路题 )
考虑对立情况,不漂亮的串的形式必然为GGGGR……R……RGGGG 相邻R之间的距离为奇数且相等. #include <cstdio> #include <cstring> # ...
- iOS大神班笔记02-模仿苹果创建单例
首先我们得要知道苹果是如何实现单例的:1.不能外界调用alloc,一调用就崩掉,其实就是抛异常(类内部第一次调用alloc就不崩溃,其他都崩溃). 2.提供一个方法给外界获取单例. 3.内部创建一次 ...
- POJ 2195 Going Home | 带权二分图匹配
给个地图有人和房子 保证人==房子,每个人移动到房子处需要花费曼哈顿距离的代价 问让人都住在房子里最小代价 显然是个带权二分图最大匹配 转化成以一个网络,规定w是容量,c是代价 1.S向人连边,w=1 ...
- POJ 2406 Power Strings 暴力
emmmm 显然的是a串长度是s串长度的因数 我们可以暴力枚举因数然后暴力check #include<cstdio> #include<algorithm> #include ...