删除数据库表数据

背景

研发库,单节点mysql数据库。某日志表数据量过大(千万级别),需要清除部分数据(比如:只保留近一个月的数据)。

措施

使用delete删除符合条件行数据。

问题

执行效率很慢。

原因:”delete语句执行删除的过程是每次从表中删除一行,并且同时将该行的删除操作作为事务记录在日志中保存 以便进行进行回滚操作。”

文章结尾会给出相关对比

采用创建临时表

  1. 将要保留的近一个月数据放到临时表中。比如:日志表为t_change_log。
1
create table t_change_log_tmp as (select * from t_change_log where create_time>'2017-01');

注意:此方法创建出的临时表中结构属性会丢失,如表主键等。

调整后

1
2
3
4
-- 复制表结构
create table t_change_log_tmp like t_change_log;
-- copy数据
insert into t_change_log_tmp (select * from t_change_log where create_time>'2017-01');

引申

  1. create table like方式会完整地克隆表结构,但不会插入数据,需要单独使用insert into或load data方式加载数据。
  2. create table as 方式会部分克隆表结构,完整保留数据。
    3.create table as select .. where 1=0 会克隆部分表结构,但不克隆数据。
  3. 如果启用了gtid,create table as方式不被支持。收到ERROR 1786 (HY000): CREATE TABLE … SELECT is forbidden when @@GLOBAL.ENFORCE_GTID_CONSISTENCY = 1。
  1. 使用drop删除老表

    1
    drop table t_change_log;
  2. 重命名临时表为老表

    1
    alter table t_change_log_tmp rename t_change_log;

其他

drop,truncate,delete对比

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1、drop (删除表):删除内容和定义,释放空间。简单来说就是把整个表去掉.以后要新增数据是不可能的,除非新增一个表。

drop语句将删除表的结构被依赖的约束(constrain),触发器(trigger)索引(index);依赖于该表的存储过程/函数将被保留,但其状态会变为:invalid。

2、truncate (清空表中的数据):删除内容、释放空间但不删除定义(保留表的数据结构)。与drop不同的是,只是清空表数据而已。

注意:truncate 不能删除行数据,要删就要把表清空。

3、delete (删除表中的数据):delete 语句用于删除表中的行。delete语句执行删除的过程是每次从表中删除一行,并且同时将该行的删除操作作为事务记录在日志中保存以便进行进行回滚操作。

truncate与不带where的delete :只删除数据,而不删除表的结构(定义)

4、truncate table 删除表中的所有行,但表结构及其列、约束、索引等保持不变。新行标识所用的计数值重置为该列的种子。如果想保留标识计数值,请改用delete。
如果要删除表定义及其数据,请使用 drop table 语句。

5、对于由foreign key约束引用的表,不能使用truncate table ,而应使用不带where子句的delete语句。由于truncate table 记录在日志中,所以它不能激活触发器。

6、执行速度,一般来说: drop> truncate > delete。

7、delete语句是数据库操作语言(dml),这个操作会放到 rollback segement 中,事务提交之后才生效;如果有相应的 trigger,执行的时候将被触发。

truncate、drop 是数据库定义语言(ddl),操作立即生效,原数据不放到 rollback segment 中,不能回滚,操作不触发 trigger。

参考:http://www.cnblogs.com/1312mn/p/4422396.html

Alan Zhang wechat
欢迎您扫一扫上面的微信公众号“补愚者说”,订阅我的博客!