【Oracle】Oracle 12c DB In-Memory入门实验手册(三)

(三)IM列压缩

之前的两篇我们分别介绍了以下两部分内容,感兴趣的朋友可以去看一下:

基础篇:http://blog.csdn.net/badly9/article/details/49746825

加载数据到IMhttp://blog.csdn.net/badly9/article/details/49777993


CREATE或者ALTER时使用MEMCOMPRESS sub-clause可以设置表、分区和列水平上的压缩方式。举例说明,对于单个表,出于业务考虑,可能有的列更看重查询速度,有些则不在意查询速度更在意占用空间的大小,这时候对于不同的列则可以采用不同的压缩方式。

默认的压缩方式为MEMCOMPRESS FOR QUERY LOW。在这种压缩方式下,Oracle的读取速度最快,因为在这种压缩方式下,Oracle不需要解压缩就可以直接读取数据,比NO COMPRESS都要更快。其他压缩方式下,比如FOR QUREY HIGHFOR CAPACITY,使用了其他的压缩算法,Oracle需要解压缩之后才能查看数据。下面列出了IM所有的压缩方式:

NO MEMCOMPRESS:数据加载过程中不进行任何压缩。

MEMCOMPRESS FOR DML:针对DML操作进行的最小程度的压缩以保证性能。

MEMCOMPRESS FOR QUERY LOW:针对查询性能优化的压缩方式(default

MEMCOMPRESS FOR QUERY HIGH:除了查询性能也平衡了存储空间,但更偏向查询性能。

MEMCOMPRESS FOR CAPACITY LOW:平衡了性能与空间节省方面,但是更偏向于空间节省。

MEMCOMPRESS FOR CAPACITY HIGH:只从空间节省出发进行优化

 

3.1 默认压缩级别

在对表开启IM后,如果没有指定压缩级别则为默认压缩级别,为FOR QUERY LOW

 

实验过程如下:

1.创建测试表SALES_INM

SQL> CREATE TABLE SALES_INM INMEMORY AS SELECT * FROM SALES;

 

Table created.

2.查看测试表SALES_INM表的IM属性:

SQL> COL SEGMENT_NAME FORMAT A30

SQL> SELECT SEGMENT_NAME, INMEMORY, INMEMORY_COMPRESSION FROM

  2  USER_SEGMENTS WHERE SEGMENT_NAME = 'SALES_INM';

 

SEGMENT_NAME                   INMEMORY INMEMORY_COMPRESS

------------------------------ -------- -----------------

SALES_INM                      ENABLED  FOR QUERY LOW

可以看到此时的默认压缩级别为FOR QUERY LOW

3.通过查询将表加载到IM中。

SQL> SELECT COUNT(*) FROM SALES_INM;

 

  COUNT(*)

----------

    918843

 

SQL> COL OWNER FORMAT A20

SQL> SELECT OWNER, SEGMENT_NAME, POPULATE_STATUS, BYTES_NOT_POPULATED

  2  FROM V$IM_SEGMENTS WHERE SEGMENT_NAME = 'SALES_INM';

 

OWNER                SEGMENT_NAME         POPULATE_ BYTES_NOT_POPULATED

-------------------- -------------------- --------- -------------------

BADLY9              SALES_INM            COMPLETED                   0

4.查看压缩之后的表大小

SQL> SELECT V.OWNER, V.SEGMENT_NAME,

  2  V.BYTES ORIG_SIZE,

  3  V.INMEMORY_SIZE IN_MEM_SIZE,

  4  V.BYTES/V.INMEMORY_SIZE COMP_RATIO

  5  FROM V$IM_SEGMENTS V

  6  WHERE SEGMENT_NAME = 'SALES_INM';

 

OWNER                SEGMENT_NAME          ORIG_SIZE IN_MEM_SIZE COMP_RATIO

-------------------- -------------------- ---------- ----------- ----------

BADLY9              SALES_INM              12582912     8585216 1.46564885

该表在disk中大小为12582912字节,加载压缩后为8585216字节,比例为为1.4661

 

3.2 CAPACITY HIGH 压缩级别

刚才测试了QUERY LOW压缩级别,现在来测一下CAPACITY HIGH的压缩级别。

实验过程如下:

1.创建测试表SALES_INM2,压缩级别为CAPACITY HIGHPRIORITYHIGH

SQL> CREATE TABLE SALES_INM2 INMEMORY MEMCOMPRESS FOR CAPACITY HIGH

  2  PRIORITY HIGH AS SELECT * FROM SALES;

 

Table created.

2.确认一下SALES_INM2IM属性

SQL> COL SEGMENT_NAME FORMAT A20

SQL> SELECT SEGMENT_NAME, INMEMORY, INMEMORY_PRIORITY,

  2  INMEMORY_COMPRESSION FROM USER_SEGMENTS

  3  WHERE SEGMENT_NAME = 'SALES_INM2';

 

SEGMENT_NAME         INMEMORY INMEMORY INMEMORY_COMPRESS

-------------------- -------- -------- -----------------

SALES_INM2           ENABLED  HIGH     FOR CAPACITY HIGH

3.确认SALES_INM2已经加载完毕

SQL> COL OWNER FORMAT A20

SQL> SELECT OWNER, SEGMENT_NAME, POPULATE_STATUS, BYTES_NOT_POPULATED

  2  FROM V$IM_SEGMENTS WHERE SEGMENT_NAME = 'SALES_INM2';

 

OWNER                SEGMENT_NAME         POPULATE_ BYTES_NOT_POPULATED

-------------------- -------------------- --------- -------------------

BADLY9              SALES_INM2           COMPLETED                   0

4.查看压缩比例

SQL> SELECT V.OWNER, V.SEGMENT_NAME,

  2  V.BYTES ORIG_SIZE,

  3  V.INMEMORY_SIZE IN_MEM_SIZE,

  4  V.BYTES/V.INMEMORY_SIZE COMP_RATIO

  5  FROM V$IM_SEGMENTS V

  6  WHERE SEGMENT_NAME = 'SALES_INM2';

 

OWNER                SEGMENT_NAME          ORIG_SIZE IN_MEM_SIZE COMP_RATIO

-------------------- -------------------- ---------- ----------- ----------

BADLY9              SALES_INM2             12582912     3342336 3.76470588

可以看到CAPACITY HIGH压缩级别,该表在disk中大小为12582912,压缩后为3342336,比例为3.761

 

对于各个压缩级别的压缩测试不再一一展示,针对我使用的这张表的在disk中大小与加载压缩后比例对比如下:

NO MEMCOPRESS12.65104167

FOR DML12.23

FOR QUERY LOW10.68

FOR QUERY HIGH10.43

FOR CAPACITY LOW10.34

FOR CAPACITY HIGH10.26

 

3.3针对列级别进行压缩。

在上面的实验中我们压缩针对的是整个表级别,事实上我们也可以针对不同的列使用不同的压缩级别。

 

实验过程如下:

1.修改CUSTOMERS表各列压缩级别,其中各个列压缩级别如下:

CUT_FIRST_NAMECUST_LAST_NAME的压缩级别为QUERY HIGH

CUST_STREET_ADDRESS压缩级别为CAPACITY LOW

CUST_CITY CUST_STATE_PROVINCE压缩级别为No compression

其他列压缩级别为默认。

SQL> ALTER TABLE CUSTOMERS INMEMORY

  2  INMEMORY MEMCOMPRESS FOR QUERY HIGH (CUST_FIRST_NAME,

  3  CUST_LAST_NAME)

  4  INMEMORY MEMCOMPRESS FOR CAPACITY LOW (CUST_STREET_ADDRESS)

  5  INMEMORY NO MEMCOMPRESS (CUST_CITY, CUST_STATE_PROVINCE);

 

Table altered.

2.查看各列压缩级别

SQL> SET LINES 100;

SELECT TABLE_NAME, COLUMN_NAME, INMEMORY_COMPRESSION

FROM V$IM_COLUMN_LEVEL

SQL>   2    3  WHERE TABLE_NAME = 'CUSTOMERS';

 

TABLE_NAME                      COLUMN_NAME                     INMEMORY_COMPRESSION

------------------------------- ------------------------------- --------------------------

CUSTOMERS                       CUST_ID                         DEFAULT

CUSTOMERS                       CUST_FIRST_NAME                 FOR QUERY HIGH

CUSTOMERS                       CUST_LAST_NAME                  FOR QUERY HIGH

CUSTOMERS                       CUST_GENDER                     DEFAULT

CUSTOMERS                       CUST_YEAR_OF_BIRTH              DEFAULT

CUSTOMERS                       CUST_MARITAL_STATUS             DEFAULT

CUSTOMERS                       CUST_STREET_ADDRESS             FOR CAPACITY LOW

CUSTOMERS                       CUST_POSTAL_CODE                DEFAULT

CUSTOMERS                       CUST_CITY                       NO MEMCOMPRESS

CUSTOMERS                       CUST_CITY_ID                    DEFAULT

CUSTOMERS                       CUST_STATE_PROVINCE             NO MEMCOMPRESS

CUSTOMERS                       CUST_STATE_PROVINCE_ID          DEFAULT

CUSTOMERS                       COUNTRY_ID                      DEFAULT

CUSTOMERS                       CUST_MAIN_PHONE_NUMBER          DEFAULT

CUSTOMERS                       CUST_INCOME_LEVEL               DEFAULT

CUSTOMERS                       CUST_CREDIT_LIMIT               DEFAULT

CUSTOMERS                       CUST_EMAIL                      DEFAULT

CUSTOMERS                       CUST_TOTAL                      DEFAULT

CUSTOMERS                       CUST_TOTAL_ID                   DEFAULT

CUSTOMERS                       CUST_SRC_ID                     DEFAULT

CUSTOMERS                       CUST_EFF_FROM                   DEFAULT

CUSTOMERS                       CUST_EFF_TO                     DEFAULT

CUSTOMERS                       CUST_VALID                      DEFAULT

 

23 rows selected.

3.加载该表到IM中。

SQL> EXEC DBMS_INMEMORY.REPOPULATE('BADLY9,'CUSTOMERS', FORCE=>TRUE);

 

PL/SQL procedure successfully completed.

4.确认该表已经加载到IM

SQL> SELECT SEGMENT_NAME, POPULATE_STATUS, BYTES_NOT_POPULATED

  2  FROM V$IM_SEGMENTS WHERE SEGMENT_NAME = 'CUSTOMERS';

 

SEGMENT_NAME         POPULATE_ BYTES_NOT_POPULATED

-------------------- --------- -------------------

CUSTOMERS            COMPLETED                   0

5.修改表上列的压缩属性。

SQL> ALTER TABLE CUSTOMERS INMEMORY

  2  INMEMORY MEMCOMPRESS FOR QUERY LOW (CUST_FIRST_NAME)

  3  INMEMORY MEMCOMPRESS FOR CAPACITY LOW (CUST_MAIN_PHONE_NUMBER)

  4  INMEMORY NO MEMCOMPRESS (CUST_STREET_ADDRESS);

 

Table altered.

6.查看该表上各列的压缩属性

SQL> SET LINES 100;

SQL> SELECT TABLE_NAME, COLUMN_NAME, INMEMORY_COMPRESSION

  2  FROM V$IM_COLUMN_LEVEL

  3  WHERE TABLE_NAME = 'CUSTOMERS';

 

TABLE_NAME                      COLUMN_NAME                     INMEMORY_COMPRESSION

------------------------------- ------------------------------- --------------------------

CUSTOMERS                       CUST_ID                         DEFAULT

CUSTOMERS                       CUST_FIRST_NAME                 FOR QUERY LOW

CUSTOMERS                       CUST_LAST_NAME                  FOR QUERY HIGH

CUSTOMERS                       CUST_GENDER                     DEFAULT

CUSTOMERS                       CUST_YEAR_OF_BIRTH              DEFAULT

CUSTOMERS                       CUST_MARITAL_STATUS             DEFAULT

CUSTOMERS                       CUST_STREET_ADDRESS             NO MEMCOMPRESS

CUSTOMERS                       CUST_POSTAL_CODE                DEFAULT

CUSTOMERS                       CUST_CITY                       NO MEMCOMPRESS

CUSTOMERS                       CUST_CITY_ID                    DEFAULT

CUSTOMERS                       CUST_STATE_PROVINCE             NO MEMCOMPRESS

CUSTOMERS                       CUST_STATE_PROVINCE_ID          DEFAULT

CUSTOMERS                       COUNTRY_ID                      DEFAULT

CUSTOMERS                       CUST_MAIN_PHONE_NUMBER          FOR CAPACITY LOW

CUSTOMERS                       CUST_INCOME_LEVEL               DEFAULT

CUSTOMERS                       CUST_CREDIT_LIMIT               DEFAULT

CUSTOMERS                       CUST_EMAIL                      DEFAULT

CUSTOMERS                       CUST_TOTAL                      DEFAULT

CUSTOMERS                       CUST_TOTAL_ID                   DEFAULT

CUSTOMERS                       CUST_SRC_ID                     DEFAULT

CUSTOMERS                       CUST_EFF_FROM                   DEFAULT

CUSTOMERS                       CUST_EFF_TO                     DEFAULT

CUSTOMERS                       CUST_VALID                      DEFAULT

 

23 rows selected.

7.再次查看该表是否被加载到IM中。

SQL> SELECT SEGMENT_NAME, POPULATE_STATUS, BYTES_NOT_POPULATED

  2  FROM V$IM_SEGMENTS WHERE SEGMENT_NAME = 'CUSTOMERS';

 

no rows selected

可以看到现在该表已经从IMflush出去了,因为改变了该表的压缩属性,而且没有设置PRIORITY,也没有进行重新加载,所以该表已被刷出IM区域。等待重新加载。

 

3.4 tablespace级别设置压缩级别

在之前的实验中我们也测试过可以在tablespace层面设置inmemory clause,那么针对tablespace层面进行压缩设置当然也要实验一下啦。

 

实验过程如下:

1.查看表空间目前IM属性

SQL> SELECT TABLESPACE_NAME, DEF_INMEMORY, DEF_INMEMORY_COMPRESSION

  2  FROM DBA_TABLESPACES;

 

TABLESPACE_NAME                DEF_INME DEF_INMEMORY_COMP

------------------------------ -------- -----------------

SYSTEM                         DISABLED

SYSAUX                         DISABLED

UNDOTBS1                       DISABLED

TEMP                           DISABLED

USERS                          DISABLED

RTL_DATA                       DISABLED

TBS_TEST                       DISABLED

 

7 rows selected.

2.更改表空间属性

SQL> ALTER TABLESPACE TBS_TEST DEFAULT INMEMORY MEMCOMPRESS FOR CAPACITY

  2  HIGH PRIORITY HIGH;

 

Tablespace altered.

3.查看表空间IM属性

SQL> SELECT TABLESPACE_NAME, DEF_INMEMORY,

  2  DEF_INMEMORY_COMPRESSION, DEF_INMEMORY_PRIORITY

  3  FROM DBA_TABLESPACES WHERE TABLESPACE_NAME = 'TBS_TEST';

 

TABLESPACE_NAME                DEF_INME DEF_INMEMORY_COMP DEF_INME

------------------------------ -------- ----------------- --------

TBS_TEST                       ENABLED  FOR CAPACITY HIGH HIGH

4.创建测试表SALES_INM3不添加IM参数,SALES_INM4添加IM参数

SQL> CREATE TABLE SALES_INM3 AS SELECT * FROM SALES;

 

Table created.

 

SQL> CREATE TABLE SALES_INM4 INMEMORY MEMCOMPRESS FOR QUERY HIGH AS

  2  SELECT * FROM SALES;

 

Table created.

5.查询两张测试表的IM压缩参数

SQL> COL SEGMENT_NAME FORMAT A20

SQL> SELECT SEGMENT_NAME, INMEMORY, INMEMORY_PRIORITY,

  2  INMEMORY_COMPRESSION FROM USER_SEGMENTS WHERE SEGMENT_NAME IN

  3  ('SALES_INM3','SALES_INM4');

 

SEGMENT_NAME         INMEMORY INMEMORY INMEMORY_COMPRESS

-------------------- -------- -------- -----------------

SALES_INM3           ENABLED  HIGH     FOR CAPACITY HIGH

SALES_INM4           ENABLED  NONE     FOR QUERY HIGH

注意:不知道大家是否还记得前边的文章在介绍INMEMORY_CLAUSE_DEFAULT的时候,如果创建表的时候没有设置PRIORITY,那么会自动设置为INMEMORY_CLAUSE_DEFAULT的设置,和其他参数进行一个叠加。但是如果在tablespace级别上设置了IM属性,创建表如果使用了IM属性,是不会有叠加效果的,而是单纯使用创建表时语句指定的IM属性。

7.查询一边SALES_INM4,将表加载到IM中。

SQL> SELECT COUNT(*) FROM SALES_INM4;

 

  COUNT(*)

----------

    918843

8.确认两张表都已经加载完成

SQL> COL OWNER FORMAT A20

SQL> SELECT OWNER, SEGMENT_NAME, POPULATE_STATUS, BYTES_NOT_POPULATED

  2  FROM V$IM_SEGMENTS WHERE SEGMENT_NAME IN ('SALES_INM3',

  3  'SALES_INM4');

 

OWNER                SEGMENT_NAME         POPULATE_ BYTES_NOT_POPULATED

-------------------- -------------------- --------- -------------------

BADLY9              SALES_INM3           COMPLETED                   0

BADLY9              SALES_INM4           COMPLETED                   0

9.查看两张表压缩后的大小

SQL> SELECT V.SEGMENT_NAME,

  2  V.INMEMORY_COMPRESSION,

  3  V.BYTES ORIG_SIZE,

  4  V.INMEMORY_SIZE IN_MEM_SIZE,

  5  V.BYTES/V.INMEMORY_SIZE COMP_RATIO

  6  FROM V$IM_SEGMENTS V

  7  WHERE SEGMENT_NAME IN ('SALES_INM3','SALES_INM4');

 

SEGMENT_NAME         INMEMORY_COMPRESS  ORIG_SIZE IN_MEM_SIZE COMP_RATIO

-------------------- ----------------- ---------- ----------- ----------

SALES_INM3           FOR CAPACITY HIGH   12582912     2228224 5.64705882

SALES_INM4           FOR QUERY HIGH      12582912     5439488 2.31325301

最后将tablespace重新改为NO INMEMORY,这两张表的IM属性不变,这里就不再贴实验过程。也就是说tablespace的修改只针对后来新建的表生效。

 

3.5使用COMPRESSION ADVISOR

在对一张表使用COMPRESSION clause进行IM压缩级别设置之前,我们可以通过OracleCOMPRESSION ADVISOR对表放入到IM中的大小进行提前计算。COMPRESSION ADVISOR是通过对于表中的数据进行采样,然后来分析压缩后所占的空间,所以相对来说还是非常精准的。

那么接下来我们通过DBMS_COMPRESSION.GET_COMPRESSION_RATIOSALES_INM3SALES_INM4放入到IM中的压缩比率进行预估。

 

实验过程如下:

1.通过下面的语句对SALES_INM3使用CAPCATITY HIGH级别进行压缩比率估算:

SET SERVEROUTPUT ON

DECLARE

l_blkcnt_cmp PLS_INTEGER;

l_blkcnt_uncmp PLS_INTEGER;

l_row_cmp PLS_INTEGER;

l_row_uncmp PLS_INTEGER;

l_cmp_ratio PLS_INTEGER;

l_comptype_str VARCHAR2(100);

BEGIN

dbms_compression.get_compression_ratio (

-- Input parameters

scratchtbsname => 'TBS_TEST',

ownname => 'BADLY9',

objname => 'SALES_INM4',

subobjname => NULL,

comptype => dbms_compression.comp_inmemory_capacity_high,

-- Output parameter

blkcnt_cmp => l_blkcnt_cmp,

blkcnt_uncmp => l_blkcnt_uncmp,

row_cmp => l_row_cmp,

row_uncmp => l_row_uncmp,

cmp_ratio => l_cmp_ratio,

comptype_str => l_comptype_str,

subset_numrows => dbms_compression.comp_ratio_allrows);

dbms_output.put_line('Comp. ratio (Capacity High):'||l_cmp_ratio);

END;

/

输出结果:

Comp. ratio (Capacity High):5

 

PL/SQL procedure successfully completed.

可以看到输出压缩倍数为5,对比我们前边实验结果为 5.64705882,可见这个压缩比例和实际的压缩比例有差距但相差不大。

2.对SALES_INM4表使用QUERY HIGH级别,预估加载到IM中之后的压缩比率:

SET SERVEROUTPUT ON

DECLARE

l_blkcnt_cmp PLS_INTEGER;

l_blkcnt_uncmp PLS_INTEGER;

l_row_cmp PLS_INTEGER;

l_row_uncmp PLS_INTEGER;

l_cmp_ratio PLS_INTEGER;

l_comptype_str VARCHAR2(100);

BEGIN

dbms_compression.get_compression_ratio (

-- Input parameters

scratchtbsname => 'TBS_TEST',

ownname => 'BADLY9',

objname => 'SALES_INM4',

subobjname => NULL,

comptype => dbms_compression.comp_inmemory_query_high,

-- Output parameter

blkcnt_cmp => l_blkcnt_cmp,

blkcnt_uncmp => l_blkcnt_uncmp,

row_cmp => l_row_cmp,

row_uncmp => l_row_uncmp,

cmp_ratio => l_cmp_ratio,

comptype_str => l_comptype_str,

subset_numrows => dbms_compression.comp_ratio_allrows);

dbms_output.put_line('Comp. ratio (Query High):'||l_cmp_ratio);

END;

/

输出结果为:

Comp. ratio (Query High):2

 

PL/SQL procedure successfully completed.

对比我们前边的实验结果为2.31325301

自己实验的话只要把我标红的几个参数进行修改即可。

 

 

 

 

 

 

 

你可能感兴趣的:(DB,12c,In-Memory)