使用过Oracle的都知道,Truncate操作由于不需要写redo日志,因此,在性能上会比delete操作更高效,但在实际使用过程中,有时会发现delete比truncate速度更快。以下介绍下二者的机制,让大家对二者有清晰的了解。

一、大数据量删除操作

1、数据准备

创建两张没有索引的大表:t1 , t2 ,每张表的数据量接近 350W

test=# create table t2 as select * from t1;
SELECT 3461120

2、测试Delete操作

test=# checkpoint;
CHECKPOINT test=# select pg_current_wal_lsn();
pg_current_wal_lsn
--------------------
0/92DB1FC8
(1 row) test=# select relname,relfilenode from sys_class where relname='t1';
relname | relfilenode
---------+-------------
t1 | 16575
(1 row) test=# delete from t1;
DELETE 3461120
Time: 4771.554 ms (00:04.772) test=# select pg_current_wal_lsn();
pg_current_wal_lsn
--------------------
0/C87A2EC0
(1 row) test=# select pg_wal_lsn_diff('0/C87A2EC0','0/92DB1FC8');
pg_wal_lsn_diff
-----------------
899616504
(1 row)

test=# checkpoint;
CHECKPOINT

test=# select relname,relfilenode from sys_class where relname='t1';
relname | relfilenode
---------+-------------
t1 | 16575
(1 row)

结论:Delete 操作产生了近900M的日志;数据文件的relfilenode 不变。

3、测试Truncate操作

test=# checkpoint;
CHECKPOINT test=# select relname,relfilenode from sys_class where relname='t2';
relname | relfilenode
---------+-------------
t2 | 16581
(1 row) test=# select pg_current_wal_lsn();
pg_current_wal_lsn
--------------------
0/CAA7C678
(1 row) test=# truncate table t2;
TRUNCATE TABLE
Time: 84.124 ms test=# select pg_current_wal_lsn();
pg_current_wal_lsn
--------------------
0/CAA82D40
(1 row) Time: 0.327 ms
test=# select relname,relfilenode from sys_class where relname='t2';
relname | relfilenode
---------+-------------
t2 | 16587
(1 row) Time: 0.491 ms
test=# select pg_wal_lsn_diff('0/CAA82D40','0/CAA7C678');
pg_wal_lsn_diff
-----------------
26312
(1 row) Time: 1.239 ms

结论:Truncate 操作基本不产生redo;relfilenode 会变化,这是由于truncate操作相当于新建了个文件。

三、小数据量删除操作比较

1、比较一:数据未写回磁盘前,进行truncate

test=# declare
test-# v_sql text;
test-# begin
test-# for i in 1..1000 loop
test-# drop table if exists t1;
test-# create table t1 as select * from pg_class;
test-# delete from t1;
test-# end loop;
test-# end;
test-# /
ANONYMOUS BLOCK
Time: 7173.891 ms (00:07.174) test=# declare
test-# v_sql text;
test-# begin
test-# for i in 1..1000 loop
test-# drop table if exists t1;
test-# create table t1 as select * from pg_class;
test-# truncate t1;
test-# end loop;
test-# end;
test-# /
ANONYMOUS BLOCK
Time: 7477.366 ms (00:07.477)

结论:truncate 似乎更慢。从操作系统IO看,二者的IO 相差不大。

可能原因:truncate 在操作系统层面的操作实际删除旧文件,新建新文件。当调用操作系统命令删除旧文件时,需要将数据先写回文件,才能删除。而本例中,实际从create table 到truncate 时间很短,数据还未写回文件。

2、测试二:先建表,在删除数据

declare
v_sql text;
begin
for i in 1..1000 loop
v_sql = 'drop table if exists t'||i;
execute immediate v_sql;
v_sql = 'create table t'||i||' as select * from pg_class';
execute immediate v_sql;
end loop;
end; checkpoint; declare
v_sql text;
begin
for i in 1..1000 loop
v_sql = 'delete from t'||i;
execute immediate v_sql;
end loop;
end;
/
ANONYMOUS BLOCK
Time: 3412.780 ms (00:03.413) declare
v_sql text;
begin
for i in 1..1000 loop
v_sql = 'truncate t'||i;
execute immediate v_sql;
end loop;
end;
/
ANONYMOUS BLOCK
Time: 1268.753 ms (00:01.269)

结论:先建表,再checkpoint ,将数据写回数据文件。然后,再比较Delete 和 Truncate 操作,可以看到即使小表,truncate 操作也快很多。

最新文章

  1. jquery原生对象
  2. 学习SVG系列(3):SVG Stroke属性
  3. 内存只有4G的MBP要怎么破
  4. linux下配置redis
  5. cocos2d-x 屏幕坐标系和OPenGL坐标系转换
  6. classpath目录
  7. MyEclipse Spring被删之后,如何在myeclipse里面重新导入
  8. C#实现自动切割图片
  9. L-value 和 R-value.
  10. Mule与其它web应用服务器的区别
  11. 蓝桥杯之K好数问题
  12. Nginx+Php-fpm+MySQL+Redis源码编译安装指南
  13. arm nop
  14. 分布式测试工具Beetle.DT的部署并进行HTTP,SQL,TCP压测
  15. bzoj:3400 [Usaco2009 Mar]Cow Frisbee Team 奶牛沙盘队
  16. 网页加载进度的实现--JavaScript基础
  17. IDEA配置github并上传项目
  18. Spring中加载xml配置文件的常用的几种方式
  19. logstash采集与清洗数据到elasticsearch案例实战
  20. QT中设置窗口背景颜色

热门文章

  1. Jmter入门教程
  2. django--ORM表的多对一关系
  3. RPA 快手自动上传机器人
  4. Linux 文件的打包压缩
  5. LVGL库入门教程 - 动画
  6. 用python整个URL缩短器
  7. 毕设必看——Python ttkbootstrap 制作账户注册信息界面
  8. Jenkins安装插件出现Signature verification failed in update site 'default' (show details)
  9. IDEA插件配置之Eclipse Code Formatte
  10. 字节输入流_InputStream类&FileInputStream类介绍和字节输入流读取字节数据