ORACLE表压缩介绍

长期以来,压缩一直作为 Oracle 数据库特性以这样或那样的形式存在着。

  压缩始终是非常占用 CPU 的过程,并且需要花费一定时间。通常,如果压缩数据,则数据必须解压缩后才能使用。虽然此要求在数据仓库环境(SQL 通常在大量的行上运行,漫长的响应时间通常是可以容忍的)中是可以接受的,但在 OLTP 环境中可能无法接受。

  现在,在 Oracle 数据库 11g 中,可以执行以下命令:

create table my_compressed_table (
 col1 number(20),
 col2 varchar2(300),
 ...
)
compress for all operations

  “compress for all operations”子句在所有 DML 活动(如 INSERT、UPDATE 等)上执行压缩。压缩在所有 DML 活动上发生,而不像前几个版本那样,只在直接路径插入上发生。

  这会降低 DML 的速度吗?不一定。这正是该新特性的最大优点。向表中插入行时不会发生压缩。相反,在插入行时,这些行将被解压缩,然后以常规方式插入。当以解压缩方式插入(或更新)一定数量的行时,将执行压缩算法并压缩块中所有解压缩的行。换句话说,将压缩块,而不是行。在 RDBMS 代码内部定义压缩发生的阈值。

  压缩机制

  请看一个 ACCOUNTS 表,它包含以下记录:

  Oracle数据库11g新特性:其他特性

  在数据库内部,假定一个数据库块包含上述所有行。

  Oracle数据库11g新特性:其他特性

  解压缩的块看上去是这样的:记录中的所有字段(列)都包含数据。压缩此块时,数据库首先计算在所有行中发现的重复值,将这些值移出行外,然后将其放在块的头部附近。行中的这些重复值将被替换为一个表示其中每个值的符号。从概念上讲,它看上去如下图所示,您可以看到压缩前后的块。

  Oracle数据库11g新特性:其他特性

  注意这些值是如何从行中取出并放入顶部称为“符号表”的特殊区域中的。列中的每个值都被分配一个符号,此符号将替代行内的实际值。由于符号所占空间小于实际值,因此记录大小也远远小于初始值。行中的重复数据越多,符号表和块越紧凑。

  由于压缩作为触发事件发生,而不是在插入行时发生,因此在正常的 DML 进程中压缩对性能没有任何影响。压缩被触发后,对 CPU 的需求肯定会变得很高,但在其他任何时间 CPU 影响都为零,因此压缩也适用于 OLTP 应用程序,这是 Oracle 数据库 11g 中压缩的平衡点。

  除了降低空间消耗外,压缩数据还将缩短网上传输时间、减少备份空间,并使在 QA 和测试中维护生产数据库的完整副本变得切实可行。

  COPY 仍然存在!

  与传言相反,COPY 命令仍然存在。并且它仍然是复制 LONG 数据类型的唯一方式。但由于此命令已被弃用,因此它已经跟不上 Oracle 数据库的发展步伐。

  例如,它不知道存在新的数据类型 BFILE.如果您尝试复制包含 BFILE 类型列(如先前的示例中所示)的 DOCS 表:

SQL> copy to sh@oradba11 -
> replace docs_may08 -
> using select * from docs
> where creation_dt between '1-may-08' and '31-may-08';
Enter TO password:
Array fetch/bind size is 15. (arraysize is 15)
Will commit when done. (copycommit is 0)
Maximum long size is 80. (long is 80)
CPY-0012: Datatype cannot be copied

  错误消息描述的是:COPY 命令无法复制 BFILE 数据类型。但如果表中包含 Long 类型列,则无法使用 INSERT /*+ APPEND */ 和 CREATE TABLE ……NOLOGGING AS SELECT …… 语句。在以下示例中,我们尝试将一个表中的某些行复制到另一个表中,第二个表中有一个定义为 LONG 类型的列:

SQL>create table mytab1 as select * from mytab where col1 = 'A';
create table mytab1 as select * from mytab
               *
ERROR at line 1:
ORA-00997: illegal use of LONG datatype
SQL> insert /*+ APPEND */ into mytab
 2> select * from mytab where col1 = 'A';
select * from mytab
    *
ERROR at line 2:
ORA-00997: illegal use of LONG datatype

  因此,要复制大量数据而不填充还原段,唯一简单的方法就是使用 COPY 命令。

  导出和导入:濒临废弃

  在 Oracle 数据库 10g 中引入数据泵时,预计最终将废弃传统的导出和导入工具。那么,请继续等待:在 Oracle 数据库 11g 中,这些旧工具仍然存在。由于已被弃用,这些工具不会再得到任何增强,但绝不能说它们是无用的。

  就功能而言,数据泵胜过常规导入/导出许多倍,但在一种简单情况下,后者仍然非常有用:当您必须在客户端而不是服务器上创建转储文件时。由于执行操作前不必创建目录,因此在许多方面,通过常规导出/导入执行简单的数据导出可能更容易。

  但是,需要再次声明的是,由于这些工具已被弃用,因此在使用时存在以下三个风险:

  ■ Oracle 不再为这些工具添加任何功能,因此可能不支持将来的数据类型等。

  ■ 这些工具可能会在未经事先声明的情况下从将来的版本中删除,您以后必须重写代码。

  ■ 如果您遇到错误,Oracle 支持部门可能会拒绝修复该代码。

  因此,可能有必要将现有代码转换为数据泵,并且为了适应新发展,也确实应该这样做。

  增量更新的全局统计信息

  在分区表中,每个分区都可以有优化程序统计信息。此外,在整个表上还有与分区无关的全局统计信息,例如,整个表中不同值的数量。仅在 dbms_stats.gather_*_stats 程序发出指令时才会收集此全局统计信息,默认情况下不会收集。如果未指定全局统计信息参数,则不会收集全局统计信息,优化程序将根据分区统计信息生成全局统计信息。当然,计算得到的全局统计信息始终要比生成的统计信息精确,因此始终建议您收集全局统计信息。

  但是,过去一直存在一个小问题:当分区数据变化但其他分区保持不变时,全局统计信息可能会变得陈旧。因此,即使只有一个分区发生变化,统计信息收集程序也必须遍历整个表来收集全局统计信息。

  现在这个问题已不复存在。在 Oracle 数据库 11g 中,可以指示优化程序仅从更改的分区中以增量方式收集全局统计信息,而不必再次执行整表扫描。通过将用于统计信息收集的表参数 INCREMENTAL 设置为 TRUE 可完成此操作,如下所示:

begin
  dbms_stats.set_table_prefs(
      'SH','SALES','INCREMENTAL','TRUE');
end;
/

  现在,您应该专门收集此表中粒度为 AUTO 的分区 SALES_1995 上的统计信息。

begin
  dbms_stats.gather_table_stats (
      ownname     => 'SH',
      tabname     => 'SALES',
      partname    => 'SALES_1995',
      granularity   => 'AUTO'
  );
end;

  此统计信息收集方法指示数据库根据从新分区收集的统计信息,以增量方式更新全局统计信息。

  数据泵功能改进

  正如我先前提到的,自上一个版本开始,数据泵工具一直用于移动大量数据,或者对数据进行有效的“逻辑”备份。与导出/导入类似,它是独立于平台的工具(例如,可以从 Linux 导出,然后再导入 Solaris)。在 Oracle 数据库 11g 中,数据泵获得了一些增强。

  数据泵存在的较大问题之一是,创建转储文件时无法对其进行压缩。在较旧的导出/导入实用程序中,这一点比较容易做到。在 Oracle 数据库 11g 中,数据泵可以在创建转储文件时对其进行压缩。这是通过在 expdp 命令行中使用参数 COMPRESSION 实现的。此参数有三个选项:

  ■ METDATA_ONLY — 仅压缩元数据;数据保持原样(在 Oracle 数据库 10.2 中同样可用)。

  ■ DATA_ONLY — 仅压缩数据;元数据保持原样。

  ■ ALL — 同时压缩元数据和数据。

  ■ NONE — 此为默认选项;不执行任何压缩。

  下面说明如何压缩 UNITS_FACT 表的导出内容:

$ expdp global/global directory=dump_dir tables=units_fact dumpfile=units_fact_comp.dmp compression=all

  为了便于比较,下面说明如何只导出而不压缩:

$ expdp global/global directory=dump_dir tables=units_fact dumpfile=units_fact_uncomp.dmp

  现在,如果您查看所创建的文件:

$ ls -l
-rw-r----- 1 oracle dba 2576384 Jul 6 22:39 units_fact_comp.dmp
-rw-r----- 1 oracle dba 15728640 Jul 6 22:36 units_fact_uncomp.dmp

  压缩比例为 100*(15728640-2576384)/15728640,大约为 83.61%!这是一个相当大的压缩比例;解压缩的转储文件为 15MB,而压缩后的转储文件为 1.5MB.如果使用 gzip 压缩转储文件:

$ gzip units_factl_uncomp.dmp
-rw-r----- 1 oracle dba 3337043 Jul 6 22:36 units_fact_uncomp.dmp.gz

  压缩后的文件大约为 3.2MB,其大小是数据泵中压缩文件的二倍。因此,除了压缩可能会更加高效,解压缩也真正带来了好处。导入转储文件时,导入不必先解压缩文件;它将在读取文件时进行解压缩,从而使此过程真正变快。

猜你喜欢

转载自andyniu.iteye.com/blog/1922837