一 现象描述web
Delete是oracle数据库中的经常使用操做,尤为是在自动化测试中,初始化环境、前置准备都不可避免的进行增删操做,但持续一时间后,可能会碰到表空间不足这类报错现象,这就不由纳闷儿了,明明插入数据前会有删除的,数据总量并无呈现明显的量级变化,为何表占用空间却在偷偷增大呢?数据库
二 现象分析oracle
出现上述现象的缘由是Delete操做并不会释放占用的空间。在讲解缘由以前,先了解下oracle中高水位线的概念,有助于理解delete操做产生的这种现象。app
所谓的高水位(HWM),通俗的讲就是一个标记,用来记录已经有多少数据块(Block)分配给表,能够拿水库的历史最高水位来类比,当使用delete操做后,数据虽然被删除了,但这个高水位的标记并无下降,就比如水库的历史最高水位不会由于水被释放了而下降。于是,原则上在没有外部干预的条件下,这个高水位标记值只会增大,不会下降。ide
三 实战模拟重现现象测试
根据上面的现象描述和分析,接下来,我会用具体的实例模拟该现象,使你们能够更直观的了解。spa
第1,建立一张测试表test,具体字段不须要关心,只要知道初始了存储空间为100M,如图所示:3d
第2,建立完成后,咱们查看下数据表占用的空间,如图所示:orm
其中,查询前须要对表进行分析,使用命令为:ANALYZE TABLE test ESTIMATE STATISTICS;查询语句为:SELECT blocks, empty_blocks, num_rows FROM user_tables WHERE table_name = 'TEST';blog
注意上面三个字段的结果:BLOCKS=0; EMPTY_BLOCKS=13312; NUM_ROWS=0,即当前表占用的块数为0,默认1 BLOCK = 8kb,预分配的块为13312,行数为0。
一切都没有问题,新建立的表,没有数据嘛,固然行数为0,占用块数为0喽。
第3,写一个语句块,循环插入1000条语句,再次对test表进行分析、查询,结果以下:
从图中能够看到,占用BLOCKS=222,NUM_ROWS=1000,合乎逻辑,插入了1000条数据,占用了空间嘛。
第4,使用Delete语句删除1000条数据,再次对test表进行分析、查询,结果倒是以下:
从上图中能够清楚的看到,数据被删除后,NUM_ROWS=0了,可是BLOCKS并无被置为0,也就是这部分数据块仍然被认为是占用的。
所以,就出现了本文一开始就提到的现象,随着不断的插入、删除数据,BLOCKS也会不断扩大,尽快delete操做后,可能表中数据量不多,但表占用的存储空间未减小。
四 解决方法
针对delete操做引发的空间不释放现象,或者,更正式一点的说法,如何下降高水位线,方法有不少种,如,shrink space;move tablespace;create table xxx as select * from xxx 重建表等。使用这些方法前,咱们的原则是:
若是能够truncate,直接truncate,该操做会重置高水位线,BLOCKS会被置为0,NUM_ROWS置为0;不然,优先使用shrink space,该方法不须要重建索引。
接着上面第4步,咱们使用shrink space下降高水位线,释放空间,其中,使用shrink space命令前,须要先alter table test enable row movement;开启行移动,再次对表进行分析、查询,结果以下:
从图中能够看出,此时BLOCKS已经被置为0了,可是,细心的你可能也发现, EMPTY_BLOCKS已经不是初始的13312,而是此时的40,这说明shrink space不只会释放高水位线如下的空间,也会释放申请的空间,即高水位线上下都有操做,这也是与move、truncate的不一样,它们只能释放高水位线如下的空间。
五 shrink space经常使用操做命令
Shrink space的经常使用命令以下:
六 Delete操做的潜在影响
根据上述分析,delete操做产生的潜在影响以下:
1. 全表扫描一般要读出直到HWM标记的全部属于该表的数据块,即便该表中没有任何数据;(形成查询变慢)
2. 插入操做时使用append关键字,即便HWM如下有空闲的数据库块,插入时使用HWM以上的数据块;(形成HWM自动增大)
七 总结
经过上文的现象描述和分析,随着insert的不断操做,高水位线也随着不断增长,尽管delete了数据,但高水位线并无降低,致使表占用的空间没有释放。所以,在实际应用中,若是可能,尽可能使用truncate,并且该操做高效、快速;不然要考虑下delete操做遗留的影响,使用合适的方法整理空间。