truncate/drop表非常慢,怎么办?用硬链接,极速体验
这个这个,我必须花巨大篇幅,记录下今天清空表记录的英雄壮举,可知道一个drop操作,执行了一下午啊一下午,这是要急出翔的节奏。。呵呵,下面开始
我的需求:某表因历史原因,积压了1亿条记录,约占360G空间。我要清掉它,就是这么简单。
尝试1:作为DB小菜,首先想到的,当然是delete命令。于是欢快的执行了delete from mytable; 知道吗?一杯茶都喝完了,它还没有执行完。我的尊严受到了挑战,捉急了,开始google。
尝试2:好,换用truncate命令。truncate table mytable; 知道吗?第二坏茶喝完了,它还没有执行完。快急出翔了,继续google。
尝试3:好,干脆drop表好了。drop table mytable; 知道吗?第三杯茶喝完了,它还没有执行完。这下快吓尿了,这是什么情况。。。赶快找大牛问
当然,drop之前别忘了先备份一下表结构,一会儿drop完了还得重新建表,那得多麻烦呀,嘿嘿
create table mytable_bak like mytable; // 备份
drop table mytable; // 删表
alter table mytable_bak rename to mytable; // 重新命名
尝试4:大牛说,不妨改一下这两个开关,可以加速drop。于是,又等了10min,窗外雨都下停了,还是没有执行完。。。
truncate有索引的表和没有索引的表速度一样吗?
每天晚上凌晨先truncate掉我们系统中的表,然后采集当天的数据到数据库。采集方式是用ctl控制文件方法导出db文件再把db文件导入我们数据库的方法,不是直接insert。
采集到我们系统中的表有20张,数据量为1000W以上的大概有八张,我把这20张表称为原始表。我们用这20张原始表通过SQL查询语句与对应的业务需求做成10张报表(结果表)。
因为有几张表数据量很大,所以查询起来的时候速度很慢,所以想到了建立索引的方式来提高效率。
1
|
insert into 结果表1 select col1,col2,col3... from 原始表1,原始表2 where XXX and XXX.... |
上面是我们生成报表的的类似语句。
那么问题来了:
1,我所了解的索引一般是建立在不常变更的表上面的,但是我们的表每天都会被truncate,这样是不是会影响效率?truncate有索引和没索引的表速度一样么?
2,虽然我们的数据不是用insert到数据库的,导入数据会因为表有索引会对导入速度有影响么?顺便问下,如果insert到数据库,因为存在索引,是不是效率很低?
3,有没有什么其他好办法来提高效率。
2,索引会降低表导入速度
3,把文件放在在数据库服务器上用数据库自带工具导入(如果能保证逻辑正确,导入前删掉索引 触发器 主键之类的,导完之后 在建索引触发器 主键)
2 索引会影响导入数据,建议先导入所有数据后再建立索引
其语法结构为:
TRUNCATE [TABLE] tbl_name
这里简单的给出个示例,
我想删除 friends 表中所有的记录,可以使用如下语句:
truncate table friends;
delete的效果有点像将mysql表中所有记录一条一条删除到删完,而truncate相当于保留mysql表的结构,重新创建了这个表,所有的状态都相当于新表。
语法:
delete语句的定义。
DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name
[WHERE where_definition]
[ORDER BY ...]
[LIMIT row_count]
MySQL的这些语法都和口语类似,你要指出你想从哪个表删除数据,还有删除哪些数据,这就够了。就像写记叙文的时候,时间、地点、人物、环境、情节几要素必不可少一样。
示例是最形象,最能说明问题的。所以,不整没用的了,直接进入主题。按照上面的语法结构,我想删除 firends 表中所有 user_name 等于 simaopig 的记录,
就可以使用如下SQL语句:
delete from friends where user_name = 'simaopig';delete
注意事项:
从语法结构中,我们就可以看出,和 update 语法一样,我们是可以省略 where 子句的。不过这是一个很危险的行为。因为如果不指定 where 子句,delete 将删除表中所有的记录,而且是立即删除,即使你想哭都没有地方,也没有时间,因为你需要马上和主管承认错误,并且立即找出MySQL日志,来回滚记录。不过一旦你有过一次这样的经历,我相信这一定是印象深刻的。
奇怪的是我在innodb上以及myisam上大数据量下,索引文件极大的情况下,几乎不可能删除成功!留待解决。
总结
不过truncate命令快规快,却不像delete命令那样对事务处理是安全的。因此,如果我们想要执行truncate删除的表正在进行事务处理,这个命令就会产生退出并产生错误信息。
Check DB Server环境.
1 察看内存以及缓存
top - 07:55:56 up 256 days, 4:53, 3 users, load average: 0.00, 0.09, 0.22
Tasks: 175 total, 1 running, 174 sleeping, 0 stopped, 0 zombie
Cpu0 : 2.2%us, 0.9%sy, 0.0%ni, 96.4%id, 0.4%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu1 : 2.4%us, 1.1%sy, 0.0%ni, 96.0%id, 0.4%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu2 : 2.3%us, 0.9%sy, 0.0%ni, 96.3%id, 0.4%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu3 : 2.2%us, 0.9%sy, 0.0%ni, 96.4%id, 0.4%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 32750360k total, 32472008k used, 278352k free, 271932k buffers
Swap: 4194296k total, 505844k used, 3688452k free, 3554324k cached
2 察看系统版本
[novamysqladminlt@nucltmapc04db01 ~]$ cat /etc/issue
Red Hat Enterprise Linux Server release 6.3 (Santiago)
Kernel
on an m
3 察看操作系统位数
[xxxxx@xxxxxx~]$ ldd /sbin/mii-tool
linux-vdso.so.1 => (0x00007fff9b1ff000)
libselinux.so.1 => /lib64/libselinux.so.1 (0x0000003ec2400000)
libc.so.6 => /lib64/libc.so.6 (0x0000003ec0c00000)
libdl.so.2 => /lib64/libdl.so.2 (0x0000003ec0800000)
/lib64/ld-linux-x86-64.so.2 (0x0000003ec0400000)
4 察看磁盘
[xxx@xxx~]$ vmstat 1
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 505928 274840 272104 3558732 0 0 3 58 0 0 2 1 96 0 0
0 0 505928 274732 272104 3558772 0 0 0 112 1036 1438 1 1 98 0 0
1 2 505928 274732 272104 3558812 0 0 0 1796 960 1276 1 2 96 2 0
1 0 505928 269112 272104 3558836 0 0 0 5564 2005 1861 12 5 83 1 0
0 0 505928 274484 272104 3558864 0 0 0 112 1568 1969 11 2 87 0 0
0 0 505928 274484 272104 3558892 0 0 0 128 924 1221 1 2 97 0 0
1 0 505928 274468 272104 3558916 0 0 0 96 1563 1268 8 3 89 0 0
5 查看io资源
[xxx@xxx~]$ iostat -x 1
Linux 2.6.32-279.14.1.el6.x86_64 (nucltmapc04db01.abn-sjl.ea.com) 08/28/2013 _x86_64_ (4 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
2.30 0.00 0.98 0.44 0.02 96.26
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await svctm %util
vda 0.04 10.93 0.16 12.11 23.96 465.30 39.87 0.07 5.51 1.98 2.42
dm-0 0.00 0.00 0.00 0.01 0.04 0.09 9.79 0.00 2.88 0.84 0.00
dm-1 0.00 0.00 0.02 0.03 0.19 0.26 8.00 0.00 10.82 0.36 0.00
dm-2 0.00 0.00 0.00 0.13 0.07 1.01 8.34 0.00 2.01 0.75 0.01
dm-3 0.00 0.00 0.00 0.35 0.04 2.81 8.08 0.01 16.10 0.31 0.01
dm-4 0.00 0.00 0.00 0.01 0.00 0.05 8.00 0.00 1.87 0.39 0.00
dm-5 0.00 0.00 0.00 0.05 0.00 0.43 8.00 0.00 2.52 0.33 0.00
dm-6 0.00 0.00 0.00 0.01 0.02 0.06 9.89 0.00 4.01 0.90 0.00
dm-7 0.00 0.00 0.00 0.00 0.00 0.00 7.96 0.00 0.61 0.56 0.00
dm-8 0.00 0.00 0.00 0.00 0.00 0.00 8.00 0.00 1.80 1.37 0.00
dm-9 0.00 0.00 0.00 0.13 0.00 1.02 8.00 0.00 1.89 0.72 0.01
dm-10 0.00 0.00 0.17 22.33 23.59 459.57 21.48 0.05 2.28 1.07 2.40
dm-11 0.00 0.00 0.00 0.00 0.00 0.00 8.00 0.00 1.37 0.77 0.00
dm-12 0.00 0.00 0.00 0.00 0.00 0.00 7.96 0.00 0.99 0.85 0.00
avg-cpu: %user %nice %system %iowait %steal %idle
1.26 0.00 1.26 0.00 0.00 97.47
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await svctm %util
vda 0.00 17.00 1.00 7.00 8.00 192.00 25.00 0.01 0.75 0.38 0.30
dm-0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
dm-1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
dm-2 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
dm-3 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
dm-4 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
dm-5 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
dm-6 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
dm-7 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
dm-8 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
dm-9 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
dm-10 0.00 0.00 1.00 24.00 8.00 192.00 8.00 0.02 0.92 0.12 0.30
dm-11 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
dm-12 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
avg-cpu: %user %nice %system %iowait %steal %idle
9.55 0.00 4.02 0.00 0.25 86.18
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await svctm %util
vda 0.00 19.00 0.00 7.00 0.00 208.00 29.71 0.00 0.14 0.14 0.10
dm-0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
dm-1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
dm-2 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
dm-3 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
dm-4 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
dm-5 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
dm-6 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
dm-7 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
dm-8 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
dm-9 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
dm-10 0.00 0.00 0.00 26.00 0.00 208.00 8.00 0.01 0.27 0.04 0.10
dm-11 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
dm-12 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
1. truncate和 delete只删除数据不删除表的结构(定义)
drop语句将删除表的结构被依赖的约束(constrain),触发器(trigger),索引(index); 依赖于该表的
存储过程/函数将保留,但是变为invalid状态.
2.delete语句是dml,这个操作会放到rollback segement中,事务提交之后才生效;如果有相应的trigger,
执行的时候将被触发.
truncate,drop是ddl, 操作立即生效,原数据不放到rollback segment中,不能回滚. 操作不触发
trigger.
3.delete语句不影响表所占用的extent, 高水线(high watermark)保持原位置不动
显然drop语句将表所占用的空间全部释放
truncate 语句缺省情况下见空间释放到 minextents个 extent,除非使用reuse storage; truncate
会将高水线复位(回到最开始).
4.速度,一般来说: drop> truncate > delete
5.安全性:小心使用drop 和truncate,尤其没有备份的时候.否则哭都来不及.
使用上,想删除部分数据行用delete,注意带上where子句. 回滚段要足够大.
想删除表,当然用drop
想保留表而将所有数据删除. 如果和事务无关,用truncate即可. 如果和事务有关,或者想触发trigger,还
是用delete.
如果是整理表内部的碎片,可以用truncate跟上reuse stroage,再重新导入/插入数据/
实际应用:
delete from table; //删除所有数据
truncate table; //将auto_increatement调制从0开始,实际就是从1开始
(1)delete在事务中可以回滚
mysql>select * from t;
+----+
| id |
+----+
| 1 |
| 2 |
+----+
2 rows inset (0.00 sec)
mysql>begin;
Query OK,0 rows affected (0.00 sec)
mysql>delete from t where id=2;
Query OK,1 row affected (0.04 sec)
mysql>select * from t;
+----+
| id |
+----+
| 1 |
+----+
1 row inset (0.00 sec)
mysql>rollback;
Query OK,0 rows affected (0.01 sec)
mysql>select * from t;
+----+
| id |
+----+
| 1 |
| 2 |
+----+
2 rows inset (0.00 sec)
(2)truncate在事务中不能回滚
mysql>begin;
Query OK,0 rows affected (0.00 sec)
mysql>truncate table t;
Query OK,0 rows affected (0.03 sec)
mysql>rollback;
Query OK,0 rows affected (0.00 sec)
mysql>select * from t;
Empty set(0.00 sec)
mysql>
标签:
股票 |
经过一个处理之后,我每次删除400万条记录花5 - 6分钟,删除全部1.6亿条记录花了4 - 5个小时!
为什么??
我在删除前先保存当前索引的DDL,然后删除其索引,
然后根据使用的删除条件建立一个临时的索引(这是提高速度的另外一个重要原因!)
开始删除操作,完成之后再重建之前的索引。
如果需要保留的数据比较少的话,可以把要保留的数据备份出来。在drop表。重新创建,先不要急着创建索引、主键,把数据导回去,然后在建索引、约束之类的。
在删除数据之前删除这两个索引,此时需要三分钟多一些,然后删除其中无用数据,此过程需要不到两分钟,删除完成后重新创建索引,因为此时数据库中的数据相对较少,约三四十万条记录(此表中的数据每小时会增加约十万条),创建索引也非常快,约十分钟左右。这样整个删除过程只需要约15分钟。对比之前的八个小时,大大节省了时间。
相同点:
truncate和不带where子句的delete, 以及drop都会删除表内的数据
不同点:
1. truncate和 delete只删除数据不删除表的结构(定义)
drop语句将删除表的结构被依赖的约束(constrain),触发器(trigger),索引(index); 依赖于该表的存储过程/函数将保留,但是变为invalid状态.
2.delete语句是dml,这个操作会放到rollback segement中,事务提交之后才生效;如果有相应的trigger,执行的时候将被触发.
truncate,drop是ddl, 操作立即生效,原数据不放到rollback segment中,不能回滚. 操作不触发trigger.
3.delete语句不影响表所占用的extent, 高水线(high watermark)保持原位置不动
显然drop语句将表所占用的空间全部释放
truncate 语句缺省情况下见空间释放到 minextents个 extent,除非使用reuse storage; truncate会将高水线复位(回到最开始).
4.速度,一般来说: drop> truncate > delete
5.安全性:小心使用drop 和truncate,尤其没有备份的时候.否则哭都来不及.
使用上,想删除部分数据行用delete,注意带上where子句. 回滚段要足够大.
想删除表,当然用drop
想保留表而将所有数据删除. 如果和事务无关,用truncate即可. 如果和事务有关,或者想触发trigger,还是用delete.
如果是整理表内部的碎片,可以用truncate跟上reuse stroage,再重新导入/插入数据/