三种删除数据命令:drop、truncate、delete区别

一、delete

1、执行delete操作时,每次从表中删除一行,并且同时将该行的的删除操作记录在redo日志和undo日志中以便进行回滚(rollback)和重做操作,但要注意表空间要足够大,特别是表比较大的情况。

2、delete可根据条件删除表中满足条件的数据,如果不指定where子句,那么删除表中所有记录。

3、delete是DML(data maintain language),delete这个操作会被放到rollback segment中,事务提交之后才会生效,如果有相应的触发器trigger,那么执行的时候可以被触发。

4、delete语句不影响表所占用的extent(就是表结构的中的区),高水线(high watermark)保持原位置不变。 (高水位线就存在于段(segment)中,它用于标识段中已使用过的数据块与未使用的数据块二者间交界,扫描表数据的时候,高水位线以下的所有数据块都必须被扫描。)

二、truncate

1、truncate是DDL(data define language)即操作会立即生效,原数据不会放到rollback segment中,不能回滚,也不会触发触发器。

2、truncate会删除表中所有记录,并且将重新设置高水线和所有的索引,缺省情况下将空间释放到minextents的extent(就是表结构中的段内的区域),除非使用reuse storage(使用这句话,所在的extent空间不会被回收,只是将数据删除掉,数据删除之后的freespace空间,只能供本表使用,其他的不可以使用)。不会记录日志,所以执行速度很快,但不能通过rollback撤消操作(如果一不小心把一个表truncate掉,也是可以恢复的,只是不能通过rollback来恢复)。

3、对于外键(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 语句。

4.truncate table不能用于参与了索引视图的表。
三、drop

1、drop是DDL,会隐式提交,所以,不能回滚,不会触发触发器。

2、drop语句删除表结构及所有数据,并将表所占用的空间全部释放。

3、drop语句将删除表的结构所依赖的约束,触发器,索引,依赖于该表的存储过程/函数将保留,但是变为invalid状态。

四、总结比较

1、一般来说执行效率:drop> truncate > delete。
从上面的介绍可以看出delete执行过程中需要需要写大量日志,在执行删除较大量数据的时候执行时间较长。
truncate和drop在执行时,记录日志很少(重做日志和回滚日志不用写,binlog只写入一条),在表记录较多时,与delete相比就节省了大量IO,执行时间就比较短。

之前写过一个案例:一个数据较多的表,按顺序删除部分旧数据。在那个案例中,就是利用drop执行快的优势,先将留下的表数据备份,然后drop表,最后在使用备份恢复数据。
注意:在使用drop和truncate时一定要注意,虽然可以恢复,但为了减少麻烦,还是要慎重。

2.如果想删除部分数据可以用delete,注意带上where子句,回滚段要足够大。
当然上面提到了一个案例用drop。但是如果删除的数据比例较小,或者是不是按照主键顺序删除,还应考虑delete。
3.如果和事务有关,或者想触发trigger,还是用delete。
    这里涉及到一些关系和逻辑,用delete还是比较省事。不过还是应具体情况具体制定方案。
4.如果想删除表,当然用drop; 

5.如果想保留表而将所有数据删除,如果和事务无关(不能回滚),用truncate即可;

    这里要注意,上面也介绍了truncate默认会重置高水线和索引,自增也会重置。

6.如果是优化表(整理表内部的碎片),可以用truncate跟上reuse stroage(或drop),再重新导入/插入数据

你可能感兴趣的:(MySQL)