oracle中delete与trucate

本文详细对比了Oracle中delete和truncate操作的区别,包括数据删除、表和索引占用空间变化、重建索引对空间的影响及操作性能。阐述了如何在不同场景下选择合适的操作以优化数据库管理。
转帖:
http://hi.baidu.com/victor036/blog/item/d14024432ef1b41c72f05dfb.html

oracle中delete与trucate的区别2010-10-20 13:45
1.准备数据与相关表
drop table dt_test_tab;
create table dt_test_tab (i number);
create index dt_test_idx on dt_test_tab(i);
insert into dt_test_tab values (1);
insert into dt_test_tab select i from dt_test_tab; / ... / 共17次得到131072条记录,然后
commit;
2.查看新增加纪录的结果:
select sum(bytes)/1024 from user_extents where segment_name='DT_TEST_IDX'; 结果为4352k

truncate table dengtaotest;
select sum(bytes)/1024 from user_extents where segment_name='DT_TEST_IDX'; 结果为128k(就是建表建索引时缺省的initial extent,看来是缩回去了)

alter index dt_test_idx rebuild;
select sum(bytes)/1024 from user_extents where segment_name='DT_TEST_IDX'; 结果还是128K. 想缩到0, 没门儿

再试试表,索引,delete/truncate reuse|drop storage 的结果:

select sum(bytes)/1024 from user_extents where segment_name='DT_TEST_TAB'; 表大小为:3328K (比索引还小,特例,因为表只一个字段)
select sum(bytes)/1024 from user_extents where segment_name='DT_TEST_IDX'; 索引大小为:4352K


删掉一半数据:
delete dt_test_tab where rownum < 65536;
select sum(bytes)/1024 from user_extents where segment_name='DT_TEST_TAB'; 表大小未变:3328K 注意此时还没有commit;
select sum(bytes)/1024 from user_extents where segment_name='DT_TEST_IDX'; 索引大小未变:4352K

commit;
select sum(bytes)/1024 from user_extents where segment_name='DT_TEST_TAB'; 删掉一半记录后表大小未变:3328K
select sum(bytes)/1024 from user_extents where segment_name='DT_TEST_IDX'; 删掉一半记录后索引大小未变:4352K [删了记录,index 也未释放]


alter index dt_test_idx rebuild;
select sum(bytes)/1024 from user_extents where segment_name='DT_TEST_IDX'; 删掉一半记录后重建索引,索引大小为:2200K [重建索引后,有所释放]


truncate table dt_test_tab reuse storage;
select sum(bytes)/1024 from user_extents where segment_name='DT_TEST_TAB'; 重用存贮区的截表,表大小不变:3328K
select sum(bytes)/1024 from user_extents where segment_name='DT_TEST_IDX'; 重用存贮区的截表,索引大小同样未变:2200K

truncate table dt_test_tab;
select sum(bytes)/1024 from user_extents where segment_name='DT_TEST_TAB'; SUM(BYTES)/1024 --------------- 128
select sum(bytes)/1024 from user_extents where segment_name='DT_TEST_IDX'; SUM(BYTES)/1024 --------------- 128
不重用存贮区的截表,结果变了,缩回到了initial extents
[结论]
1、delete,表占用空间不变,这个众所周知,所谓的water-mark不变;表上索引占用空间也不会变;
2、truncate table tb_name reuse storage,表占用不变,表上索引占用也不会变;
3、truncate table tb_name,表与表上索引的空间占用均回到建立索引或表时的initial参数。
4、定期rebuild索引是一个好习惯,一是提高索引效率二是释放存贮区。
补充参数:

  TRUNCATE TABLE name [DROP/REUSE STORAGE]

  DROP STORAGE:显式指明释放数据表和索引的空间

  REUSE STORAGE:显式指明不释放数据表和索引的空间

Truncate table 表名 速度快,而且效率高,因为:

  TRUNCATE TABLE 在功能上与不带 WHERE 子句的 DELETE 语句相同:二者均删除表中的全部行。但 TRUNCATE TABLE 比 DELETE 速度快,且使用的系统和事务日志资源少。

  DELETE 语句每次删除一行,并在事务日志中为所删除的每行记录一项。TRUNCATE TABLE 通过释放存储表数据所用的数据页来删除数据,并且只在事务日志中记录页的释放。

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

  对于由 FOREIGN KEY 约束引用的表,不能使用 TRUNCATE TABLE,而应使用不带 WHERE 子句的 DELETE 语句。由于 TRUNCATE TABLE 不记录在日志中,所以它不能激活触发器。

  TRUNCATE TABLE 不能用于参与了索引视图的表。

  对用TRUNCATE TABLE删除数据的表上增加数据时,要使用UPDATE STATISTICS
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值