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

(二)加载数据到IM column store

在实验手册(一)中介绍了IM的基础操作,objects如何开启IM column store

链接:http://blog.csdn.net/badly9/article/details/49746825

 

虽然在之前的操作中我们对objects开启了IM column store,但是这些objects仍然没有被加载到IM column store中。默认情况下,Oracle会自主决定什么时候将表加载如IM中。或者我们可以通过执行DBMS_INMEMORY包来手动加载objectsIM中。

通过设置sub-clause PRIORITY可以自动加载objectsIM中。

 

2.1 通过查询objects来加载数据到IM

默认情况下,Oracle在第一次访问objects之后加载该objectsIM中(比如全表扫描)。如果一个object开启了IM并且被查询之后,而且如果查询需要的数据并没有被加载到IM,数据库会通过后台进程异步的从buffer cachedisk中加载需要的数据到IM中,在数据逐步加载到IM中之后,之后的查询就会可以使用IM

IM通过后台一组worker processes加载数据。每个worker process负责加载该objects的一部分。加载使用的是流机制,同时负责将数据的分列和压缩。在这个过程中,数据库正常运行。

就如一个表空间在硬盘上被分为多个extentIM也被分成多个In-Memory Compression UnitsIMCUs)。每个worker process会被分配自己的IMCU,加载objects的子集到IMCU中。数据在被加载到IMCU的过程中不会进行任何的分类和排序。加载数据的顺序和数据行实际存储的顺序相同。IMCU的大小和数量由系统内部算法决定。

通过视图V$IM_SEGMENTSV$IM_USER_SEGMENTS能够查看objects是否被加载到IM中以及加载状态。如果segment仅仅设置了IM相关属性而没有被加载,则在这两个视图中并不会有与该segment对应的数据。

 

实验过程如下:

1.将sales表开启IM

SQL> ALTER TABLE SALES INMEMORY;

 

Table altered.

2.查询数据字典来确认表是否开启IM

SQL> SELECT INMEMORY, INMEMORY_PRIORITY, INMEMORY_COMPRESSION,

  2  INMEMORY_DISTRIBUTE, INMEMORY_DUPLICATE

  3  FROM USER_TABLES

  4  WHERE TABLE_NAME = 'SALES';

 

INMEMORY INMEMORY INMEMORY_COMPRESS INMEMORY_DISTRI INMEMORY_DUPL

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

ENABLED  NONE     FOR QUERY LOW     AUTO            NO DUPLICATE

3.查看V$IM_SEGMENTS的结构

SQL> DESC V$IM_SEGMENTS

 Name                                      Null?    Type

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

 OWNER                                              VARCHAR2(128)

 SEGMENT_NAME                                       VARCHAR2(128)

 PARTITION_NAME                                     VARCHAR2(128)

 SEGMENT_TYPE                                       VARCHAR2(18)

 TABLESPACE_NAME                                    VARCHAR2(30)

 INMEMORY_SIZE                                      NUMBER

 BYTES                                              NUMBER

 BYTES_NOT_POPULATED                                NUMBER

 POPULATE_STATUS                                    VARCHAR2(9)

 INMEMORY_PRIORITY                                  VARCHAR2(8)

 INMEMORY_DISTRIBUTE                                VARCHAR2(15)

 INMEMORY_DUPLICATE                                 VARCHAR2(13)

 INMEMORY_COMPRESSION                               VARCHAR2(17)

 CON_ID                                             NUMBER

4.查询V$IM_SEGMENTS中的数据

SQL> SELECT OWNER, SEGMENT_NAME, POPULATE_STATUS, BYTES_NOT_POPULATED

  2  FROM V$IM_SEGMENTS;

 

no rows selected

可以看到虽然表sales设置了IM相关属性,但是由于没有加载,在V$IM_SEGMENTS中找不到与之对应的数据。

5.通过全表扫描读取sales表,由于表上有index,在count操作中可能会用到,所以使用了hint通过全表扫描读取数据。

SQL> SELECT /*+ FULL (s) */ COUNT(*) FROM SALES s;

 

  COUNT(*)

----------

    918843

6.在执行上边的语句的时候可以看到ora_w***_orcl进程占用更多资源,这个进程就是用于加载数据到IM的后台进程。

7.查询V$IM_SEGMENTS中的数据

SQL> col owner for a10

SQL> col SEGMENT_NAME for a10

SQL> SELECT OWNER, SEGMENT_NAME, POPULATE_STATUS, BYTES_NOT_POPULATED

  2  FROM V$IM_SEGMENTS;

 

OWNER      SEGMENT_NA POPULATE_ BYTES_NOT_POPULATED

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

BADLY9    SALES      COMPLETED                   0

可以看到对SALES表的加载已经完成,还有0 bytes的数据没有加载。

8.我们可以通过V$IM_SEGMENTS视图查看该objectsIM中真正存储的大小,该视图中bytes列代表的是该表存储在磁盘上占的空间大小,INMEMORY_SIZE代表存储到IM中之后的大小。

SQL> SELECT OWNER, SEGMENT_NAME, BYTES, INMEMORY_SIZE

  2  FROM V$IM_SEGMENTS;

 

OWNER      SEGMENT_NA      BYTES INMEMORY_SIZE

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

BADLY9    SALES        33554432       7536640

可以看到SALES表在IM中经过QUERY LOW压缩后只占到在硬盘中存储的22%左右,压缩比例还是很可观的。

9.清理实验环境,将SALES置为NO INMEMORY

SQL> ALTER TABLE SALES NO INMEMORY;

 

Table altered.

10.查询V$IM_SEGMENTS进行确认

SQL> SELECT OWNER, SEGMENT_NAME, BYTES, INMEMORY_SIZE

  2  FROM V$IM_SEGMENTS;

 

no rows selected

 

2.2 通过使用DBMS_INMEMORY来加载数据

DBMS_INMEMORY包提供了两个PROCEDURE来手工加载数据到IM中:

Ø POPULATE:强制加载给定的表

Ø REPOPULATE:强制重新加载给定的表,在该表已经至少加载过一次之后才可使用。

 

实验过程如下:

1.将sales表开启IM

SQL> ALTER TABLE SALES INMEMORY;

 

Table altered.

2.查询V$IM_SEGMENTS视图,确认sales表没有被加载到IM

SQL> SELECT OWNER, SEGMENT_NAME, POPULATE_STATUS, BYTES_NOT_POPULATED

  2  FROM V$IM_SEGMENTS;

 

no rows selected

3.手工执行DBMS_INMEMORY.POPULATE procedure来加载sales表到IM

SQL> EXEC DBMS_INMEMORY.POPULATE('BADLY9','SALES');

 

PL/SQL procedure successfully completed.

4.查询V$IM_SEGMENTS视图,确认sales表已经加载到IM

SQL> SELECT OWNER, SEGMENT_NAME, POPULATE_STATUS, BYTES_NOT_POPULATED

  2  FROM V$IM_SEGMENTS;

 

OWNER      SEGMENT_NA POPULATE_ BYTES_NOT_POPULATED

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

BADLY9    SALES      COMPLETED                   0

5.通过关闭IM、重新开启IM来清除存储sales表数据的IMCU

SQL> ALTER TABLE SALES NO INMEMORY;

 

Table altered.

 

SQL> ALTER TABLE SALES INMEMORY;

 

Table altered.

6.通过DBMS_INMEMORY.REPOPULATE prcedureFORCE=>TRUE选项来加载SALES表到IM中。FORCE=>TRUE选项强制进行一次完整重新载入,类似于full refresh

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

 

PL/SQL procedure successfully completed.

7.查询V$IM_SEGMENTS视图,确认sales表已经加载到IM

SQL> SELECT OWNER, SEGMENT_NAME, POPULATE_STATUS, BYTES_NOT_POPULATED

  2  FROM V$IM_SEGMENTS;

 

OWNER      SEGMENT_NA POPULATE_ BYTES_NOT_POPULATED

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

BADLY9    SALES      COMPLETED                   0

8.关闭sales表的IM设置

SQL> ALTER TABLE SALES NO INMEMORY;

 

Table altered.

 

2.3 通过设置PRIORITY clause自动加载数据

通过设置PRIORITY clause可以设置objects在数据库open之后,objectalter之后,或者objects导入数据后自动加载objectsIM中。PRIORITY clause5个级别,分别是:NONELOWMEDIUMHIGHCRITICAL。只有在高级别的objects被加载到IM之后,比它级别低的objects才会开始加载到IM。(当然,如果一个objects被扫描则会立即加载到IM中,不受PRIORITY clause影响)

PRIORITY clause的默认值为none,代表着如果object没有被扫描则不会被主动加载到IM中。

加载算法在单实例和RAC环境中会有所不同,在下面的文章会介绍。

由于IM中的数据只存储在内存中而不会存储到disk中。所以每次数据库实例重启之后,整个IM的数据都要从disk中重新加载并进行列化处理。

 

实验过程如下:

1.将测试表SALESPRIORITY级别改为HIGH

SQL> ALTER TABLE SALES INMEMORY PRIORITY HIGH;

 

Table altered.

2.将测试表CUSTOMERSPRIORITY级别改为MEDIUM

SQL> ALTER TABLE CUSTOMERS INMEMORY PRIORITY MEDIUM;

 

Table altered.

3.将测试表COSTPRIORITY级别改为LOW

SQL> ALTER TABLE COSTS INMEMORY PRIORITY LOW;

 

Table altered.

4.使用下面的语句查看这三张表的加载顺序:

COL OBJECT_NAME FORMAT A15

SELECT a.OBJECT_NAME, b.INMEMORY_PRIORITY, b.POPULATE_STATUS,

TO_CHAR(c.CREATETIME, 'MM/DD/YYYY HH24:MI:SS.FF2') START_POP,

TO_CHAR(MAX(d.TIMESTAMP),'MM/DD/YYYY HH24:MI:SS.FF2') FINISH_POP

FROM DBA_OBJECTS a, V$IM_SEGMENTS b,

V$IM_SEGMENTS_DETAIL c, V$IM_HEADER d

WHERE OBJECT_NAME IN ('CUSTOMERS','SALES','COSTS')

AND a.OBJECT_NAME = b.SEGMENT_NAME

AND a.OBJECT_TYPE = 'TABLE'

AND a.OBJECT_ID = c.BASEOBJ

AND c.DATAOBJ = d.OBJD

GROUP BY a.OBJECT_NAME, b.INMEMORY_PRIORITY, b.POPULATE_STATUS,

c.CREATETIME

ORDER BY FINISH_POP;

 

OBJECT_NAME     INMEMORY POPULATE_ START_POP              FINISH_POP

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

SALES           HIGH     COMPLETED 11/10/2015 00:14:29.97 11/10/2015 00:14:31.43

CUSTOMERS       MEDIUM   COMPLETED 11/10/2015 00:16:27.67 11/10/2015 00:16:28.01

COSTS           LOW      COMPLETED 11/10/2015 00:16:28.59 11/10/2015 00:16:28.72

可以看到SALESCUSTOMERSCOSTS三张表的加载顺序为:SALES=>CUSTOMERS=>COSTS

5.现在我们来重启一下数据库来看一下加载顺序:

conn / as sysdba

shutdown immediate

startup

COL OBJECT_NAME FORMAT A15

SELECT a.OBJECT_NAME, b.INMEMORY_PRIORITY, b.POPULATE_STATUS,

TO_CHAR(c.CREATETIME, 'MM/DD/YYYY HH24:MI:SS.FF2') START_POP,

TO_CHAR(MAX(d.TIMESTAMP),'MM/DD/YYYY HH24:MI:SS.FF2') FINISH_POP

FROM DBA_OBJECTS a, V$IM_SEGMENTS b,

V$IM_SEGMENTS_DETAIL c, V$IM_HEADER d

WHERE OBJECT_NAME IN ('CUSTOMERS','SALES','COSTS')

AND a.OBJECT_NAME = b.SEGMENT_NAME

AND a.OBJECT_TYPE = 'TABLE'

AND a.OBJECT_ID = c.BASEOBJ

AND c.DATAOBJ = d.OBJD

GROUP BY a.OBJECT_NAME, b.INMEMORY_PRIORITY, b.POPULATE_STATUS,

c.CREATETIME

ORDER BY FINISH_POP;

 

OBJECT_NAME     INMEMORY POPULATE_ START_POP              FINISH_POP

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

SALES           HIGH     COMPLETED 11/10/2015 00:24:23.59 11/10/2015 00:24:24.85

CUSTOMERS       MEDIUM   COMPLETED 11/10/2015 00:24:24.86 11/10/2015 00:24:25.25

COSTS           LOW      COMPLETED 11/10/2015 00:24:25.26 11/10/2015 00:24:25.41

结果和我们之前的验证相同,都是先加载完高级别的objects才会开始加载低级别的objects

 

2.4 RAC环境下

DUPLICATE clause

RAC环境中,每个节点拥有自己的IM Area。一个objects根据DUPLICATE clause的设置将一样的数据加载到多个IM Area中。

默认是NO DUPLICATE设置,表示在数据库的IM中对一个objects在所有节点中合起来只保存一份。举例说明,比如三节点的RAC中,对于分区表SALES来讲可能2012年份的数据在1节点,2013年份的数据在2节点,2014年份的数据在3节点,每个分区只保存在一个节点上。

为了提升可用性,也可以设置为DUPLICAET ALL,在每个节点上都保存一份。举例说明,还是刚才那个SALES表的请款下,123三个节点各保存一份完整sales表数据到各自的IM中。在任意一个节点上都可以获取查询需要的数据。

在设置为DUPLICATE ALL的情况下

DISTRIBUTE clause

如果一个objects因为太大无法被加载到一个IM Area中,还可以通过DISTRIBUTE clause的设置将它分成几个数据片分别加载到不同的节点中。

默认情况下DISTRIBUTE clause的默认值为AUTO-DISTRIBUTE,这时候是否将objects分布式分布在不同的节点上由Oracle内部算法决定。这个参数对于单实例没有影响,在RAC环境中,默认存在IM中的表会分布在各个节点之中。

 

 

 

 

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