Oracle 11.2 中的压缩和高级压缩

Tags: database oracle

在之前的文章中,我们讨论了 Hybrid Columnar Compression -- 针对 Exadata 和 使用 Exadata storage 系统的压缩方式。当然这不是唯一的压缩选项,还有另外两种:BASIC 和 OLTP,他们并不是高级压缩方式并且可以在 non-Exadata storage 上使用。让我们再回顾一下 HCC 的选项并且与 BASIC 和 OLTP 进行比较。我们将从 BASIC 和 OLTP 压缩开始然后再回顾 HCC 压缩类型。

Oracle 11.2.0.x 支持(开箱即用)两种表压缩方式:BASIC 和 OLTP。BASIC 就像它名字暗示的那样,使用基础的压缩算法进行压缩。现在让我们看看 BASIC 到底能节省多少空间:

SQL> select segment_name, sum(bytes) total_space
  2  from user_segments
  3  group by segment_name;

SEGMENT_NAME                        TOTAL_SPACE 
--  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  -- - --  --  --  --  -- -
DEPT                                      65536
DUMMY                                     65536
EMP                                   713031680
SALGRADE                                  65536

SQL> alter table emp move compress;

Table altered.

SQL> select segment_name, sum(bytes) total_space
  2  from user_segments
  3  group by segment_name;

SEGMENT_NAME                        TOTAL_SPACE 
--  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  -- - --  --  --  --  -- -
DEPT                                      65536
DUMMY                                     65536
EMP                                   184549376
SALGRADE                                  65536

SQL>

还不错,现在让我们更新 EMP 表的一些数据,然后看看已使用的空间上发生了什么:

SQL> update emp set sal=5001 where sal=5000;

1048576 rows updated.

SQL> commit;

Commit complete.

SQL> select segment_name, sum(bytes) total_space
  2  from user_segments
  3  group by segment_name;

SEGMENT_NAME                        TOTAL_SPACE 
--  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  -- - --  --  --  --  -- -
DEPT                                      65536
DUMMY                                     65536
EMP                                   234881024
SALGRADE                                  65536

SQL>

更新操作使 Oracle 先解压缩要更新的行,因此增加了表所使用的空间。你可以在更新后重新压缩表不过这个会非常麻烦,你需要为那些插入、更新和删除的表准备一个存储过程来实现重新压缩动作;另一个方法是编写一个定时任务在夜间重新压缩表。

OLTP 压缩的工作方式有少许不同,当它压缩数据时,当数据块使用完后,会自动重新压缩数据块。让我们看看使用 OLTP 压缩相同表的情况,首先需要解压缩这张表:

SQL> alter table emp move nocompress;

Table altered.

SQL> select segment_name, sum(bytes) total_space
  2  from user_segments
  3  group by segment_name;

SEGMENT_NAME                        TOTAL_SPACE 
--  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  -- - --  --  --  --  -- -
DEPT                                      65536
DUMMY                                     65536
EMP                                   645922816
SALGRADE                                  65536

SQL>

有趣的是,解压缩的表比原先的表要小一些,可能的原因是无用的 NULL 字节被删除了(仅是猜测)。使用 OLTP 压缩以及更新相同的数据会得到以下结果:

SQL> alter table emp move compress for oltp;

Table altered.

SQL> select segment_name, sum(bytes) total_space
  2  from user_segments
  3  group by segment_name;

SEGMENT_NAME                        TOTAL_SPACE 
--  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  -- - --  --  --  --  -- -
DEPT                                      65536
DUMMY                                     65536
EMP                                   184549376
SALGRADE                                  65536

SQL> update emp set sal=5000 where sal=5001;

1048576 rows updated.

SQL> commit;

Commit complete.

SQL> select segment_name, sum(bytes) total_space
  2  from user_segments
  3  group by segment_name;

SEGMENT_NAME                        TOTAL_SPACE 
--  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  -- - --  --  --  --  -- -
DEPT                                      65536
DUMMY                                     65536
EMP                                   201326592
SALGRADE                                  65536

SQL>

注意,刚刚通过 OLTP 压缩的数据与使用 BASIC 压缩后的大小是一样的;差别在于更新后的压缩数据大小。这就是 OLTP 压缩机制所不同的地方,当更新快不足时会自动出触发重新压缩(re-compression)机制。

HCC 与 BASIC 和 OLTP 的方式不同,它会将数据重新组织到压缩单元中(Compression Units, CU)。记住 HCC 压缩的两种压缩方式, QUERY 和 ARCHIVE,以及这两种方式的两种压缩等级 LOW 和 HIGH。我们将使用之前文章的示例来实际看看这两种压缩方式,首先是 QUERY:

SQL> 
SQL> -- SQL> -- Current storage for the EMP table
SQL> -- (this is simply a test table for this example)
SQL> -- SQL> select segment_name, sum(bytes) total_space
  2  from user_segments
  3  group by segment_name;

SEGMENT_NAME                        TOTAL_SPACE 
--  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  -- - --  --  --  --  -- -
DEPT                                      65536
DUMMY                                     65536
EMP                                   713031680
EMP_IDX                               478150656
SALGRADE                                  65536

Elapsed: 00:00:00.82
SQL> 
SQL> -- SQL> -- Compress the table for query high (use HCC)
SQL> -- SQL> -- Note elapsed time to compress
SQL> -- SQL> alter table emp move compress for query high;

Table altered.

Elapsed: 00:00:35.65
SQL> 
SQL> -- SQL> -- Index is now invalid
SQL> -- SQL> -- Must rebuild to make it usable
SQL> -- SQL> -- Note elapsed time
SQL> -- SQL> alter index emp_idx rebuild;

Index altered.

Elapsed: 00:01:13.70
SQL> 
SQL> -- SQL> -- Current compression type, storage for table/index
SQL> -- initially after compression is enabled
SQL> -- SQL> select table_name, compression, compress_for
  2  from user_tables;

TABLE_NAME                     COMPRESS COMPRESS_FOR
 --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  -- 
DEPT                           DISABLED
BONUS                          DISABLED
SALGRADE                       DISABLED
DUMMY                          DISABLED
EMP                            ENABLED  QUERY HIGH

Elapsed: 00:00:00.20
SQL> 
SQL> select segment_name, sum(bytes) total_space
  2  from user_segments
  3  group by segment_name;

SEGMENT_NAME                        TOTAL_SPACE 
--  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  -- - --  --  --  --  -- -
DEPT                                      65536
DUMMY                                     65536
EMP                                     8388608
EMP_IDX                               260046848
SALGRADE                                  65536

Elapsed: 00:00:00.03
SQL>

压缩效果比 BASIC 和 OLTP 好很多,即使是 QUERY LOW 的压缩比仍然比 OLTP 高很多:

SQL> 
SQL> -- SQL> -- Initial storage
SQL> -- SQL> select segment_name, sum(bytes) total_space
  2  from user_segments
  3  group by segment_name;

SEGMENT_NAME                        TOTAL_SPACE 
--  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  -- - --  --  --  --  -- -
DEPT                                      65536
DUMMY                                     65536
EMP                                   713031680
EMP_IDX                               478150656
SALGRADE                                  65536

Elapsed: 00:00:00.25
SQL> 
SQL> -- SQL> -- Compress for QUERY LOW
SQL> -- SQL> -- Note elapsed time
SQL> -- SQL> alter table emp move compress for query low;

Table altered.

Elapsed: 00:00:16.16
SQL> 
SQL> alter index emp_idx rebuild;

Index altered.

Elapsed: 00:00:43.08
SQL> 
SQL> -- SQL> -- These figures are the same as those generated
SQL> -- AFTER the HCC compressed data was updated the first time
SQL> -- SQL> select table_name, compression, compress_for
  2  from user_tables;

TABLE_NAME                     COMPRESS COMPRESS_FOR
 --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  -- 
DEPT                           DISABLED
BONUS                          DISABLED
SALGRADE                       DISABLED
DUMMY                          DISABLED
EMP                            ENABLED  QUERY LOW

Elapsed: 00:00:00.02
SQL> 
SQL> select segment_name, sum(bytes) total_space
  2  from user_segments
  3  group by segment_name;

SEGMENT_NAME                        TOTAL_SPACE 
--  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  -- - --  --  --  --  -- -
DEPT                                      65536
DUMMY                                     65536
EMP                                    14680064
EMP_IDX                               260046848
SALGRADE                                  65536

Elapsed: 00:00:00.02
SQL>

QUERY 压缩类型的目的是节省空间,不过需要注意的是,如果更新已压缩的表(无论是 QUERY LOW 或 QUERY HIGH)那么表的压缩方式会回退为 OLTP re-compression 方式。

HCC 的 ARCHIVE 压缩方式的压缩效果更好,不过它的目的是压缩哪些只读数据和归档后偶尔使用的数据:

SQL> -- SQL> -- Current storage for the EMP table
SQL> -- (this is simply a test table for this example)
SQL> -- SQL> select segment_name, sum(bytes) total_space
  2  from user_segments
  3  group by segment_name;

SEGMENT_NAME                        TOTAL_SPACE 
--  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  -- - --  --  --  --  -- -
DEPT                                      65536
DUMMY                                     65536
EMP                                   713031680
EMP_IDX                               478150656
SALGRADE                                  65536

Elapsed: 00:00:00.02
SQL> 
SQL> -- SQL> -- Compress the table for archive high
SQL> -- SQL> -- Note elapsed time to compress
SQL> -- SQL> alter table emp move compress for archive high;

Table altered.

Elapsed: 00:00:38.55
SQL> 
SQL> -- SQL> -- Index is now invalid
SQL> -- SQL> -- Must rebuild to make it usable
SQL> -- SQL> -- Note elapsed time
SQL> -- SQL> alter index emp_idx rebuild;

Index altered.

Elapsed: 00:00:39.45
SQL> 
SQL> -- SQL> -- Current compression type, storage for table/index
SQL> -- initially after compression is enabled
SQL> -- SQL> select table_name, compression, compress_for
  2  from user_tables;

TABLE_NAME                     COMPRESS COMPRESS_FOR
 --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  -- 
DEPT                           DISABLED
BONUS                          DISABLED
SALGRADE                       DISABLED
DUMMY                          DISABLED
EMP                            ENABLED  ARCHIVE HIGH

Elapsed: 00:00:00.02
SQL> 
SQL> select segment_name, sum(bytes) total_space
  2  from user_segments
  3  group by segment_name;

SEGMENT_NAME                        TOTAL_SPACE 
--  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  -- - --  --  --  --  -- -
DEPT                                      65536
DUMMY                                     65536
EMP                                     4194304
EMP_IDX                               260046848
SALGRADE                                  65536

Elapsed: 00:00:00.01
SQL>

压缩后节省了大量的空间,将表由原先的 680MB 所见到 4MB,压缩率为 99.41%。使用 ARCHIVE LOW 同样能得到令人影响深刻的结果:

SQL> -- SQL> -- Initial storage
SQL> -- SQL> select segment_name, sum(bytes) total_space
  2  from user_segments
  3  group by segment_name;

SEGMENT_NAME                        TOTAL_SPACE 
--  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  -- - --  --  --  --  -- -
DEPT                                      65536
DUMMY                                     65536
EMP                                   713031680
EMP_IDX                               478150656
SALGRADE                                  65536

Elapsed: 00:00:01.31
SQL> 
SQL> -- SQL> -- Compress for ARCHIVE LOW
SQL> -- SQL> -- Note elapsed time
SQL> -- SQL> alter table emp move compress for archive low;

Table altered.

Elapsed: 00:00:34.16
SQL> 
SQL> alter index emp_idx rebuild;

Index altered.

Elapsed: 00:00:48.44
SQL> 
SQL> -- SQL> -- These figures are the same as those generated
SQL> -- AFTER the HCC compressed data was updated the first time
SQL> -- SQL> select table_name, compression, compress_for
  2  from user_tables;

TABLE_NAME                     COMPRESS COMPRESS_FOR
 --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  -- 
DEPT                           DISABLED
BONUS                          DISABLED
SALGRADE                       DISABLED
DUMMY                          DISABLED
EMP                            ENABLED  ARCHIVE LOW

Elapsed: 00:00:00.03
SQL> 
SQL> select segment_name, sum(bytes) total_space
  2  from user_segments
  3  group by segment_name;

SEGMENT_NAME                        TOTAL_SPACE 
--  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  -- - --  --  --  --  -- -
DEPT                                      65536
DUMMY                                     65536
EMP                                     8388608
EMP_IDX                               260046848
SALGRADE                                  65536

Elapsed: 00:00:00.02
SQL>

虽然使用 ARCHIVE LOW 的压缩结果比使用 ARCHIVE HIGH 大了一倍,不过任然有 98.82% 的压缩率,这与 QUERY HIGH 的压缩情况相同。ARCHIVE 压缩方式与 QUERY 压缩方式存在相同的警告,更新使用 ARCHIVE 压缩的表会使 Oracle 将表恢复为 OLTP 压缩方式,并且数据目录反馈的压缩类型不会改变。

压缩(Compression)是用来节省空间的非常有效的工具,不过你需要意识到当你更新使用 Exadata 并使用任何一种 HCC 压缩方式压缩的表时压缩类型会被改变。同样,需要意识到 BASIC 压缩类型并不会自动 re-compress 已更新数据,要控制合理的压缩比例需要一些手动或定时任务。因此,如果你打算压缩活动表,那么使用 OLTP 压缩方式是最好的选择。

本文链接:http://www.4byte.cn/learning/37777/oracle-11-2-zhong-de-ya-suo-he-gao-ji-ya-suo.html



相关文章