数据压缩

数据压缩属于海量数据处理的技术,优势有:

  • 节省空间
  • 提高数据处理效率
  • 减少内存和I/O开销

原理:

压缩数据块时,数据库首先计算再所有行中发现的重复值,将这些值移出行外,然后将其放在块的头部附近。行中的这些重复值将被替换为一个表示其中每个值的符号。

列中的每个值都被分配一个符号,此符号将替代行内的实际值。由于符号所占用空间小于实际值,因此记录大小也远远小于初始值。行中的重复数据越多,符号表和块越紧凑。

数据压缩不适合OLTP系统:

  • 数据块内的行数变多

    • 事务的争用
  • 处理数据需要更多的时间

    • 数据插入、修改的时间变长
    • 索引键值更新的时间变长

应用场景:

  • 静态数据的处理
  • 海量数据的处理

    • 减少处理的数据块
    • 减少I/O和内存的消耗
  • 历史数据进行压缩存储

    • 减少磁盘空间
    • 提高查询效率
  • 数据备份前进行压缩处理

    • 提高数据的备份和恢复时间

数据压缩技术的应用

分区表中、分区索引是可以单独压缩的,这在实际中非常有用。

在海量数据的数据库中,由于不断有新的数据加载到数据库中,旧的数据就要做过期化处理,或者备份后删掉,或者转入到离线数据库,或者对这些数据做压缩,或者做成只读表空间保存在当前数据库中,以减少对数据库的资源消耗。

可以通过user_tab_partitions查看分区的压缩属性:

  1. select * from user_tab_partitions;

可以直接将整个表做压缩:

alter table t1 compress;

对整个表做的压缩,查看user_tab_partitions分区属性时看不到分区压缩属性。

也可以在创建表和分区时对分区进行压缩:

create table t1
(
    id int,
    name varchar2(2000)
)
partition by range(id)
(
    partition p1 values less than(1000) compress,  -- p1分区做压缩
    partition p2 values less than(maxvalue)  -- p2分区不压缩
)
as select object_id,object_name from dba_objects;

如果p1分区创建时没有压缩,后来需要改为压缩:

alter table t1 modify partition p1 compress;

分区索引也可以进行分区压缩,但是和表压缩有区别:如果要对分区索引进行压缩,需要在索引对象级别设置为压缩,否则Oracle不允许单独将索引分区的属性设置为压缩。

-- 先将整个索引对象都设置为压缩
create index t1_idx on t1(id) local compress;
-- 此时,该索引对象下的所有分区索引也都自动设置成了压缩
-- 然后我们就可以将不需要压缩的索引分区属性修改为不压缩
alter index t1_idx rebuild partition p4 nocompress;

DML操作和数据压缩

只有以下几种情况,会发生数据的压缩处理,其他的DML操作时不会对数据进行压缩的:

  • alter table move
  • create table as select
  • insert /*+ append */
  • sqlldr direct path

正常insert的数据并不会被压缩。

对于update操作,如果数据本身已经被压缩,通过update修改后的数据将不再被压缩了。也就是说,update操作会对要操作的数据进行解压缩操作。

正常情况下,压缩的数据是不应该做update操作的。

假设我们的OLTP系统数据量非常大,并且按照时间有分区,那么可以:

  • 将分区表的分区属性值压缩
  • 按照这个属性,创建新的分区
  • 对于老的分区,通过alter table move partition方式将分区的数据进行压缩