翻译来源:http://docs.oracle.com/cd/E11882_01/server.112/e25494/tables002.htm#CJAGFBFG
Oracle支持在表空间(tablespace)、数据表(table)和分区(Partition)级别的压缩,如果设置为表空间级别,那么默认将该表空间中的全部的表都进行压缩。
压缩操作可以在数据单条插入、数据修改和数据批量导入时发生。
一、 压缩类型
Oracle支持下面几种表压缩方式:
其中,OLTP压缩可以在数据单条插入、数据修改、数据批量导入的时候进行压缩,其它三种只能在批量导入的时候进行。
- Basic compression:可以压缩来自通过文件路径的导入,并且只支持某些特定类型的数据和有限的几种SQL操作;
- OLTP compression:用于OLTP应用,并且可以支持全部的SQL操作;
- Warehouse compression和Archive compression:可以实现*别的压缩,因为它们采用了混合列压缩(Hybrid Columnar Compression)技术。
所谓混合列存储,就是在以行存储占主要地位的数据库中实现行列存储模式,将同一列的数据放在一起存储,可以增大压缩比,因为同一列的数据在相似度上更大。但是因为改变了原有的行结构,所以在对压缩数据进行修改的时候,Oracle会将这些数据解压,并且重新变为行存储的结构,这样在后续的修改的时候就不用再进行解压操作了。所以这种方式只能用在修改操作不是很多的情形。
如果想实现混合列压缩的高压缩比,那么只能在通过文件路径导入的数据的情况,对于传统单条插入和修改的操作,这种技术会因为由列存储到行存储的转换而降低压缩比。
下面的表格给出了这几中压缩算法的特点:
对于上面介绍的几种压缩方式,可以在创建表时在CREATE TABLE语句中利用COMPRESS子句进行说明。对于那些已经包含了数据的数据表,可以利用ALTER TABLE进行压缩说明。如果这样做,那么只有对于修改了表以后导入的数据才会被压缩,而原来已有的数据是不会被压缩的。同样道理,如果想把一个采取了压缩技术的数据表改变为没压缩的,也可以利用ALTER TABLE语句,但是只有对后续插入的数据起作用,对于原有的数据仍然是压缩状态。
在Warehouse compression中,默认的压缩级别为COMPRESS
FOR
QUERY
HIGH
,这样级别可以保证在使用混合列压缩处理Exadata存储(Exadata Storage是Oracle同时支持OLTP和OLAP的数据库应用)的时候实现较高的压缩比和压缩效率。相反,COMPRESS
FOR
QUERY
LOW
级别则是支持更快的数据导入速度。
在Archive compression中,默认的级别为COMPRESS FOR ARCHIVE LOW,它支持高压缩比和非频繁的数据访问;COMPRESS FOR ARCHIVE HIGH则对于几乎不需要访问的数据有更好的效果。
在DBMS_COMPRESSION包中提供了一个compression advisor,可以帮助我们决定使用那种压缩类型
二、压缩与分区
一个数据表中,可以同时包含压缩和没压缩的分区(partition),并且不同的分区可以使用不同类型的压缩方式,如果同时对一个数据表和其中的一个数据分区设置了不同的压缩方式,那么数据分区的设置优先级更高。
如果相对某个数据分区更改它的压缩方式,可以使用下面两种方式之一:
- 只是改变后续数据的压缩方式:使用ALTER TABLE ... MODIFY PARTITION ... COMPRESS ...
- 对于原有数据和后续数据都修改压缩方式:使用ALTER TABLE ... MOVE PARTITION ... COMPRESS ... 或者使用在线数据表重定义(online table redefinition)。
三、判断是否使用压缩
可以通过下面两种方式判断,一是查询user_tables,另一种是查询user_tab_partitions:
SQL> SELECT table_name, compression, compress_for FROM user_tables;
TABLE_NAME COMPRESSION COMPRESS_FOR
---------------- ------------ -----------------
T1 DISABLED
T2 ENABLED BASIC
T3 ENABLED OLTP
T4 ENABLED QUERY HIGH
T5 ENABLED ARCHIVE LOW
或者
SQL> SELECT table_name, partition_name, compression, compress_for
FROM user_tab_partitions;
TABLE_NAME PARTITION_NAME COMPRESSION COMPRESS_FOR
----------- ---------------- ----------- ------------------------------
SALES Q4_2004 ENABLED ARCHIVE HIGH
...
SALES Q3_2008 ENABLED QUERY HIGH
SALES Q4_2008 ENABLED QUERY HIGH
SALES Q1_2009 ENABLED OLTP
SALES Q2_2009 ENABLED OLTP
前者是在表级别的信息,后者是分区级别的信息。
除此之外,Oracle还支持判断某个数据行是否压缩。在使用混合列压缩的时候,如果对数据行进行了修改,那么压缩类型会降到一个更低的级别,比如从warehouse compression(query high)变为OLTP压缩。判断某个数据行的压缩类型,可以使用DBMS_COMPRESSION包中的GET_COMPRESSION_TYPE方法。下面的例子就是从hr.employees中查询某个行的压缩类型:
SELECT DECODE(DBMS_COMPRESSION.GET_COMPRESSION_TYPE(
ownname => 'HR',
tabname => 'EMPLOYEES',
row_id => 'AAAVEIAAGAAAABTAAD'),
1, 'No Compression',
2, 'Basic or OLTP Compression',
4, 'Hybrid Columnar Compression for Query High',
8, 'Hybrid Columnar Compression for Query Low',
16, 'Hybrid Columnar Compression for Archive High',
32, 'Hybrid Columnar Compression for Archive Low',
'Unknown Compression Type') compression_type
FROM DUAL;
通过对数据行的抽样,可以判断没有达到压缩比要求的数据行所占比例,然后可以利用ALTER TABLE 或者 MOVE PARTITION来设定一个更高级别的压缩。
四、更改压缩级别
可以在表空间、数据表和分区级别对压缩类型进行更改。
比如某个公司的销售业绩表,并且这个表按照时间进行了分区。原来这个数据表是按照warehouse compression类型进行压缩的,因为可以同时兼顾压缩比和查询效率。但是,对于那些几个月以前的分区数据,显然很少会对其进行查询。所以可以将这些分区单独设置为archive compression类型。
如果一个表已经分区,可以使用DBMS_REDEFINITION包来改变数据表的压缩级别。在进行在线重新定义(online redefinition)的时候,会产生一个临时表来存储需要重新定义的数据表,这样就可以在进行重新定义的过程中仍然支持对该表数据的访问和DML。另外,进行在线重定义所需的磁盘空间取决于设定的压缩级别和原表的大小,为了顺利进行,需要确保有足够的磁盘空间才能进行在线重定义。
如果一个表示没有经过分区的,那么可以使用ALTER TABLE ... MOVE ... COMPRESS FOR ...来改变压缩级别,但是这个过程不允许进行DML操作。
如果需要对一个分区修改压缩级别,那么可以使用ALTER TABLE ... MODIFY PARTITION;
如果需要修改表空间的压缩级别,可以使用ALTER TABLESPACE... 。
五、在压缩表中增删列
向压缩表中增加列必须满足下面两个条件:
- 基本压缩:不能为增加的列设置默认值;
- OLTP压缩:如果为增加的列设置了默认值,那么该列就必须是NOT NULL的,否则不支持。
当从压缩表中删除列时,需要满足下面的条件:
- 基本压缩:不支持删除列;
- OLTP压缩:可以支持删除列的操作,但是在删除的中间过程是将该列设置为UNUSED从而避免长时间的解压和重新压缩的操作。
六、导出和导入混合列压缩表
混合列存储的表可以通过Data Pump Import实用工具中的impdb命令进行导入,默认的impdb保持原有的表压缩特性,如果表空间不支持混合列存储,那么导入过程中会报错。
混合列存储的表还可以导入为不压缩的数据表,采用TRANSFORM:SEGMENT_ATTRIBUTES=n选项运行impdb命令。
一个没有压缩或者采用OLTP压缩机制压缩的数据表可以被转化为混合列存储模式导入,可以通过如下步骤:
- 设置表空间的默认压缩,使用ALTER TABLESPACE ... SET DEFAULT COMPRESS命令;
- 在导入过程中覆盖数据表的SEGMENT-ATTRIBUTES选项。
导出数据可以用expdb命令进行。
七、恢复混合列压缩表
可以利用备份对采用混合列压缩的表进行恢复,无论系统是否支持混合列压缩。
当系统支持的时候,可以直接利用Oracle Recovery Manager (RMAN) 进行恢复;
当不支持的时候,数据表需要先解压为没压缩的数据或者采用OLTP压缩的数据,具体按照如下步骤进行:
- 确保有足够的存储空间来完成解压工作;
- 使用UMAN对混合列压缩表进行恢复;
- 使用下面任意一条动作,完成从混合列压缩到OLTP的转化:
- 将混合列压缩转化为OLTP压缩:
ALTER TABLE table_name MOVE COMPRESS FOR OLTP;
- 将混合列压缩转化为不压缩:
ALTER TABLE table_name MOVE NOCOMPRESS;
- 将每个分区转化为不压缩:
ALTER TABLE table_name MOVE PARTITION partition_name NOCOMPRESS;
- 将数据并行转化为不压缩:
ALTER TABLE table_name MOVE NOCOMPRESS PARALLEL;
八、对压缩表的注意事项和其他限制
对于压缩了的数据表,还需要注意下面几点:
- 对于压缩的数据表是不支持在线段收缩的(Online Segment Shrink);
- 本文介绍的压缩方法不能用于SecureFiles large objects (LOBs),有专门的压缩方法处理这些数据;
- 这些压缩方法会占用CPU资源,所以需要保证有足够的CPU提供占用;
- 设置为默认压缩的数据表中pct_free(含义见下面介绍)值为0,除非人为进行其他设定。
参考:http://www.cnblogs.com/linjiqin/archive/2012/01/16/2323320.html
PCTFREE:为一个块保留的空间百分比,表示数据块在什么情况下可以被insert,默认是10,表示当数据块的可用空间低于10%后,就不可以被insert了,只能被用于update;即:当使用一个block时,在达到pctfree之前,该block是一直可以被插入的,这个时候处在上升期。
PCTUSED:是指当块里的数据低于多少百分比时,又可以重新被insert,一般默认是40,即40%,即:当数据低于40%时,又可以写入新的数据,这个时候处在下降期。