关系型表delete方式删掉大量数据后,表空间不释放

   有时候在项目中要对某些个大数据量表进行老化数据删除,delete后发现表空间没有释放,还是原来大小,这是为什么呢?在理清楚这个问题之前,我们先来理解下HWM这个概念。

什么是HWM?

   HWM——高水位线,是一个标志,用来说明已经分配给这个段的数据块的大小。当插入数据后高水位线会不断上涨,如果采用delete方式删除数据,数据虽然被删除了,但是高水位线却没有降低,还是删除数据之前那么高的水位,也就是说,这条高水位线在日常的增删操作中只会上涨,不会下跌。

HWM如何产生?

   正常的insert,delete并不会导致高水位不断增加,因为insert会优先使用delete产生的空位,只有当找不到空间时才会申请新的空间,此时才会导致HWM的上涨;另外如果持续地insert,则高水位可能持续上涨,因为已有的空间已经被占满了,当数据库使用append方式插入数据时,因为这种方式会使新插入的数据只追加到表的最后面,而不会利用原来的空数据块,也会导致HWM的上涨。

正常的insert、delete为什么不会导致高水位的增加?

   数据库存储数据到磁盘上时,是随机地分布在磁盘空白页上的,每页存储的数据零零散散没有占满空白页,清理老化数据时腾出来的空数据块的空间就比较大,足够插入这些新增的insert的数据;同理,大数据量存储时,每个空白页存储的数据可能密密麻麻,即使清理了大量的老化数据,但是平均下来每页腾出来的空白空间不足以插入新增的数据,找不到空间后就会申请新的空间,然后HWM水位线也随之上升。

HWM有什么影响吗?

   高水位会影响全表扫描,因为全表扫描扫描的是HWM以下的所有块,虽然有可能一条数据也没有,所以有同学在查表时,明明表里数据量不多,但是检索速度特别慢,刨除索引的影响,这个时候就要考虑下是否是HWM是否过高。不过高水位不会影响索引扫描。

如何释放表空间,降低HWM?

   在delete方式删除某个表的大量数据后,这个表的数据就会变得很稀疏,数据块并没有减少,HWM也并没有下降,这个时候我们就要手动收缩表空间,来释放表空间。

  1. 采用truncate语句删除老化的数据,类似于重新建表,不仅把数据都删除了,还把HWM给恢复为0,但是绝大多数情况下这种方式并不适合;

  2. SHRINK收缩表空间,mysql数据库的话则使用 OPTIMIZE TABLE.
    alter table tablename enable row movement; --开启行迁移功能
    alter table tablename_max shrink space; --(调整HWM时将阻塞DML操作),收缩表并且降低HWM
    alter table tablename_max shrink space cascade; --收缩表并降低HWM,并且回收相应的索引
    对于一些不支持收缩索引的数据库,建议重建索引: alter index indes_name rebuild online;

    rebuild和rebuild online区别:
    1. rebuild只扫描现有的索引块来实现索引重建;rebuild online实际上是扫描表而不是扫描现有的索引块来实现索引重建。
    2. rebuild online在执行期间不会阻塞DML操作,但是在开始和结束阶段,需要请求表锁,因此如果在rebuild index online开始前或结束时,有其他长时间的事务在运行,很有可能造成大量的锁等待。如果在业务期间做,可能会导致online执行很长时间;另外rebuild index online 走的是全表扫描,需要消耗大量的temp表空间(大概需要2倍的索引空间);
    而rebuild index在执行期间会阻塞DML操作,但是速度较快。
    
    rebuild index online时,系统会产生一个sys_journal_xxx的系统临时日志表,所有rebuild online时索引的变化都记录在这个表中,当新的索引创建完成后,把这和个表的记录维护到新的索引中去,然后drop掉旧的索引,这样rebuild online就完成了。
    
  3. 分区存储,一般上千万条的数据建议直接分区存储,删除老化数据时直接drop掉旧的分区,又快又干净。

你可能感兴趣的:(sql,mysql)