日期:2014-05-16 浏览次数:20416 次
? ? ? 使用表压缩来节省空间并提高查询性能。 很多决策支持系统通常都涉及到存储于几个特大表中的大量数据。随着这些系统的发展,对磁盘空间的需求也在快速增长。在当今的环境下,存储着数百TB(太字节)的数据仓库已经变得越来越普遍。
为了帮助处理磁盘容量问题,在Oracle9i第2版中引入了表压缩特性,它可以极大地减少数据库表所需要的磁盘空间数量,并在某些情况下提高查询性能。
在本文中,我将向你说明表压缩是如何工作的,以及在构建和管理数据库时如何配置表空间。我还将基于一些示例测试结构讨论一些性能问题,以帮助你了解使用表压缩预计能获得多大好处。
表压缩是如何工作的
在Orcle9i第2版中,表压缩特性通过删除在数据库表中发现的重复数据值来节省空间。压缩是在数据库的数据块级别上进行的。当确定一个表要被压缩后,数据库便在每一个数据库数据块中保留空间,以便储存在该数据块中的多个位置上出现的数据的单一拷贝。这一被保留的空间被称作符号表(symbol table)。被标识为要进行压缩的数据只存储在该符号表中,而不是在数据库行本身内。当在一个数据库行中出现被标识为要压缩的数据时,该行在该符号表中存储一个指向相关数据的指针,而不是数据本身。节约空间是通过删除表中数据值的冗余拷贝而实现的。
对于用户或应用程序开发人员来说,表压缩的效果是透明的。无论表是否被压缩,开发人员访问表的方式都是相同的,所以当你决定压缩一个表时,不需要修改SQL查询。表压缩的设置通常由数据库管理人员或设计人员进行配置,几乎不需要开发人员或用户参与。
如何创建一个压缩的表
要创建一个压缩的表,可在CREATE TABLE语句中使用COMPRESS关键字。COMPRESS关键字指示Oracle数据库尽可能以压缩的格式存储该表中的行。下面是CREATE TABLE COMPRESS语句的一个实例:
CREATE TABLE SALES_HISTORY_COMP (
PART_ID VARCHAR2(50) NOT NULL,
STORE_ID VARCHAR2(50) NOT NULL,
SALE_DATE DATE NOT NULL,
QUANTITY NUMBER(10,2) NOT NULL
)
COMPRESS
;
或者,你可以用ALTER TABLE语句来修改已有表的压缩属性,如下所示:
ALTER TABLE SALES_HISTORY_COMP COMPRESS;
为了确定是否已经利用COMPRESS对一个表进行了定义,可查询USER_TABLES数据字典视图并查看COMPRESSION列,如下面的例子所示:
SELECT TABLE_NAME, COMPRESSION FROM USER_TABLES;
TABLE_NAME COMPRESSION
------------------ -----------
SALES_HISTORY DISABLED
SALES_HISTORY_COMP ENABLED
也可以在表空间级别上定义COMPRESS属性,既可以在生成时利用CREATE TABLESPACE来定义,也可以稍后时间利用ALTER TABLESPACE来定义。与其他存储参数类似,COMPRESS属性也具有一些继承特性。当在一个表空间中创建一个表时,它从该表空间继承COMPRESS属性。为了确定是否已经利用COMPRESS对一个表空间进行了定义,可查询USER_TABLESPACES数据字典视图并查看DEF_TAB_COMPRESSION列,如下面的例子所示:
SELECT TABLESPACE_NAME,
DEF_TAB_COMPRESSION
FROM DBA_TABLESPACES;
TABLESPACE_NAME DEF_TAB_COMPRESSION
--------------- -------------------
DATA_TS_01 DISABLED
INDEX_TS_01 DISABLED
正如你所预计的那样,你可以在一个表空间直接压缩或解压缩一个表,而不用考虑表空间级别上的COMPRESS属性。
向一个压缩的表中加载数据
请注意,当你像上面那样指定COMPRESS时,你并没在实际压缩任何数据。上面的这些命令只是修改了一个数据字典的设置。只有你向一个表中加载或插入数据时才会实际压缩数据。
而且,为了确保数据被实际压缩,你需要利用一种正确的方法将数据加载或插入到表中。只有在利用以下4种方法之一批量加载或批量插入过程中才会进行数据压缩:
直接路径SQL*Loader
带有APPEND提示的串行INSERT
并行INSERT
CREATE TABLE ... AS SELECT
如果在一个平面文件中有输入数据是可用的,那么直接路径SQL*Loader方法是将这些输入数据加载至一个表格中最方便的手段。下面给出一个示例:
$sqlldr sanjay/sanjay@proddb control=sales_history.ctl direct=true
如果在一个登台表中有输入数据,那么你可以使用带有APPEND提示的串行INSERT方法或者并行INSERT方法。
作为一个例子,请看一个名为SALES_HISTORY的未压缩登台表中的可用输入数据。用串行INSERT方法时,你可以使用以下的语句向已压缩表中插入数据:
INSERT /*+ APPEND */
INTO SALES_HISTORY_COMP
SELECT * FROM SALES_HISTORY;
或者,你也可以用并行INSERT方法将数据由一个登台表转移到一个已压缩表中,如下所示:
ALTER SESSION ENABLE PARALLEL DML;
INSERT /*+PARALLEL(SALES_HISTORY_COMP,4)*/
INTO SALES_HISTORY_COMP
SELECT * FROM SALES_HISTORY;
请注意,在使用并行INSERT方法时,你需要首先利用ALTER SESSION ENABLE PARALLEL DML命令为会话期来启动并行DML。
如果输入数据位于一个平面文件中,那么你也可以使用一个外部表,然后将这些数据插入到一个压缩表中,就像这些数据放在一个登台表中可用一样。(对外部表的讨论超出了本文的范围)。
你还可以使用CREATE TABLE ... AS SELECT语句一次生成一个压缩表,并将数据插入至其中。 这里有一个例子:
CREATE TABLE SALES_HISTORY_COMP
COMPRESS
AS SELECT * FROM SALES_HISTORY;
如果你没有使用正确的加载或INSERT方法,那么即使使用COMPRESS对表格进行了定义,该表中的数据也将仍然保持未压缩状态。 例如,如果你使用惯用路径SQL*Loader或正则INSERT语句,那么数据仍然是未压缩的。
什么时候使用表压缩
Oracle数据库选择用来压缩表数据或不压缩表数据的方式已暗中牵涉到了最适合于表压缩的应用程序。如上所述,一个表中已被使用COMPRESS定义的数据,只有在使用直接路径模式被加载或利用添加(append)或并行模式被插入时,才会得到压缩。通过正则插入语句插入的数据将保持未压缩状态。
在在线事务处理(OLTP)系统中,通常是使用正则插入模式来插入数据的。因此,使用表压缩通常不会使这些表格获得太大的好处。 表压缩对于那些只加载一次但多次读取的只读表格具有最佳效果。例如,数据仓库应用程序中所