对于drop、truncate和delete,虽然简单,但是真要使用或者面试时候问到还是需要有一定的总结,自己也比较懒,前面很多人总结过了,但是并不完善,因此参看多篇文章之后进行一个总结。在此之前先简单了解下什么是DDL和DML。
DDL(数据定义语言,Data Definition Language):DDL代表数据定义语言,是一种有助于创建数据库模式的SQL命令。DDL中常用的命令有:create
,drop
,alter
,truncate
和rename
等等。
DML(数据操作语言,Data Manipulation Language):DML代表数据操作语言,是一种有助于检索和管理关系数据库中数据的SQL命令。DML中常用的命令有:insert
,update
,delete
和select
等等。
delete可根据条件删除表中满足条件的数据,如果不指定where子句,那么删除表中所有记录。delete有两种用法,一种是带where条件删除一个范围内的数据,另一种则是不带where条件全部删除。如:delete from table_name where xxx
和delete from table_name
。delete是DML,只删除数据不删除表的结构,会走事务,执行时会触发trigger。也就是说,这个操作会被放到rollback segment中,事务提交之后才会生效,如果有相应的触发器trigger,那么执行的时候可以被触发。执行delete操作时,每次从表中删除一行,并且同时将该行的的删除操作记录在redo和undo表空间中以便进行回滚(rollback)和重做操作,但要注意表空间要足够大,需要手动提交(commit)操作才能生效,可以通过rollback撤消操作。
delete语句不影响表所占用的extent(就是表结构的中的区),高水线(high watermark)保持原位置不变。 (高水位线就存在于段(segment)中,它用于标识段中已使用过的数据块与未使用的数据块二者间交界,扫描表数据的时候,高水位线以下的所有数据块都必须被扫描。)
在 InnoDB 中,delete其实并不会真的把数据删除,mysql 实际上只是给删除的数据打了个标记为已删除,因此 delete 删除表中的数据时,表文件在磁盘上所占空间不会变小,存储空间不会被释放,只是把删除的数据行设置为不可见。虽然未释放磁盘空间,但是下次插入数据的时候,仍然可以重用这部分空间(重用 → 覆盖)。
delete执行时,会先将所删除数据缓存到rollback segement中,事务commit之后生效;delete from table_name
删除表的全部数据,对于MyISAM 会立刻释放磁盘空间,InnoDB 不会释放磁盘空间;
对于delete from table_name where xxx
带条件的删除, 不管是InnoDB还是MyISAM都不会释放磁盘空间;
delete操作以后使用 optimize table table_name
则会立刻释放磁盘空间。不管是InnoDB还是MyISAM 。所以要想达到释放磁盘空间的目的,delete以后执行optimize table
操作。
truncate的作用是清空表或者说是截断表,并且重置auto_increment
的值。只能作用于表。truncate的语法很简单,后面直接跟表名即可,例如:truncate table table_name
或者 truncate table_name
。其作用是清空表中的数据, truncate和不带where子句的delete作用相同。truncate是DDL,即操作会立即生效,原数据不会放到rollback segment中,不能回滚,也不会触发触发器。
执行后立即生效,无法找回
执行后立即生效,无法找回
执行后立即生效,无法找回
truncate会立刻释放磁盘空间 ,不管是 InnoDB和MyISAM 。truncate table其实有点类似于drop table 然后creat,只不过这个create table 的过程做了优化,比如表结构文件之前已经有了等等。所以速度上应该是接近drop table的速度。
truncate速度快,而且效率高是因为使用的系统和事务日志资源少。delete语句每次删除一行,并在事务日志中为所删除的每行记录一项。truncate通过释放存储表数据所用的数据页来删除数据,并且只在事务日志中记录页的释放。
truncate会删除表中所有记录,并且将重新设置高水线和所有的索引(意思就是truncate会删除表中的所有行,但表结构及其列、约束、索引等保持不变。新行标识所用的计数值重置为该列的种子),缺省情况下将空间释放到minextents的extent(就是表结构中的段内的区域),除非使用reuse storage(使用这句话,所在的extent空间不会被回收,只是将数据删除掉,数据删除之后的freespace空间,只能供本表使用,其他的不可以使用)。不会记录日志,所以执行速度很快,但不能通过rollback撤消操作(如果一不小心把一个表truncate掉,也是可以恢复的,只是不能通过rollback来恢复)。
对于外键(foreign key )约束引用的表,不能使用 truncate table(会报错Cannot truncate a table referenced in a foreign key constraint
),也不能使用drop table(会报错Cannot delete or update a parent row: a foreign key constraint fails
),而应使用不带 where 子句的 delete 语句。此外,truncate table不能用于参与了索引视图的表。
对于MyISAM,truncate会重置auto_increment(自增序列)的值为1。而delete后表仍然保持auto_increment
。对于InnoDB,truncate会重置auto_increment的值为1。delete后表仍然保持auto_increment
。但是在做delete整个表之后重启MySQL的话,则重启后的auto_increment
会被置为1。也就是说,InnoDB的表本身是无法持久保存auto_increment
。delete表之后auto_increment
仍然保存在内存,但是重启后就丢失了,只能从1开始。实质上重启后的auto_increment会从 select 1+max(i_col) from table_name
开始,i_col为某列字段名。
执行truncate语句需要拥有表的drop权限,从逻辑上讲,truncate table类似于delete删除所有行的语句或drop table然后再create table语句的组合。为了实现高性能,它绕过了删除数据的DML方法,因此,它不能回滚。尽管truncate table与delete相似,但它被分类为DDL语句而不是DML语句。
drop作用是删除表的结构(元数据)和表数据,其用法为:drop table table_name
,drop是DDL,会隐式提交,所以,不能回滚,不会触发触发器。并且drop语句删除表结构及所有数据,并将表所占用的空间全部释放。
执行后立即生效,无法找回
执行后立即生效,无法找回
执行后立即生效,无法找回
在速度上,一般来说,drop> truncate > delete
。
1、Delete、Truncate、Drop有啥区别?我该如何选择呢?
2、Truncate用法详解
3、drop、truncate和delete的区别
4、详解SQL中drop、delete和truncate的异同