Oracle自12c版本,增加IN MEMORY选项,通过该选项在传统的事务型数据库中支持查询分析类负载。而该选型的启用,对开发者完全透明,无需做任何特殊处理。其实现过程如下图所示:
通过在SGA中设置了IM内存区,且对某张表启用IM选项后,Oracle对该表,以传统的行格式(缓冲区缓存)和列格式在SGA中同时填充数据。
1、针对查询类操作,Oracle将OLTP查询(例如主键查找)发送到缓冲区缓存,而将分析和报告查询发送到IM列存储区。在获取数据时,Oracle数据库还可以从同一查询中的两个内存区域读取数据。
2、而对DML类修改操作,仍然是更新缓冲区缓存、联机重做日志和撤消表空间。只是当启用了IM列存储后,数据库使用内部机制来跟踪数据更改,以确保IM列存储与数据库的其余部分一致。
例如,如果sales表填充在IM column store中,并且应用程序更新sales中的一行,那么数据库将自动保持IM column store中sales表的副本在事务上保持一致。
如何启用In Memory列存储模式?
数据库层面,通过设置初始化参数INMEMORY_SIZE控制是否启用In Memory选项,当设置为0禁用该选项,当设置为指定内存大小,则启用该选项,启用的最小值为100 MB。
该参数为静态参数,必须在数据库实例启动前设置,但启动后其大小可以通过alter system进行动态调整。
INMEMORY_SIZE大小是SGA_TARGET的一部分,关系如下图所示:
设置INMEMORY_SIZE后,启动数据库,可以看到如下内容,说明IN MEMORY列存储已经生效:
SQL> startupORACLE instancestarted.Total System Global Area 3019895288 bytesFixed Size 8901112 bytesVariable Size 570425344 bytesDatabase Buffers 2113929216 bytesRedo Buffers 7872512 bytesIn-Memory Area 318767104 bytesDatabase mounted.Database opened.
可以通过以下脚本查看具体设置:
SELECT NAME,VALUE/(1024*1024) "SIZE_IN_MB" FROM V$SGAWHERE NAME LIKE '%Mem%';NAME SIZE_IN_MB----------------------------------------In-Memory Area 304
相关参数:
INMEMORY_MAX_POPULATE_SERVERS。该参数控制用于IM列存储填充的最大工作进程数,默认为CPU数量的一半,该工作进程(Wnnn)填充IM列存储中的数据,压缩数据并将其转换为列格式。
列存储选项启用,可以在表、分区表、外部表、物化视图,或者表空间维度上进行设置,可以对特定列进行设置。
已有表启用IN MEMORY:
ALTER TABLE sh.customers INMEMORY;
新建表直接启用IN MEMORY:
CREATE TABLEtest_inmem( id NUMBER(5) PRIMARY KEY, test_col VARCHAR2(15)) INMEMORY;
针对特定列进行设置:
CREATE TABLE t (c1NUMBER, c2 NUMBER, c3 NUMBER)NO INMEMORY -- thisclause specifies the table itself as NO INMEMORYPARTITION BY LIST(c1)( PARTITION p1VALUES (0), PARTITION p2 VALUES (1), PARTITION p3 VALUES (2) );ALTER TABLE t NOINMEMORY (c3);ALTER TABLE t INMEMORY MEMCOMPRESS FOR CAPACITY HIGH (c1) INMEMORY MEMCOMPRESS FOR CAPACITY LOW (c2);SELECT TABLE_NAME,COLUMN_NAME, INMEMORY_COMPRESSIONFROM V$IM_COLUMN_LEVELWHERE TABLE_NAME = 'T'ORDER BYCOLUMN_NAME;TABLE_NAME COLUMN_NAME INMEMORY_COMPRESSION---------------------------------------- --------------------------T C1 FOR CAPACITY HIGHT C2 FOR CAPACITY LOWT C3 NO INMEMORY
表空间进行设置:
CREATE TABLESPACE users01 DATAFILE 'users01.dbf' SIZE 40M ONLINE DEFAULT INMEMORY;ALTER TABLESPACE users01 DEFAULT INMEMORY MEMCOMPRESS FOR CAPACITY HIGH PRIORITY LOW;SQL> select tablespace_name,DEF_INMEMORY from dba_tablespaces ;TABLESPACE DEF_INME---------- --------SYSTEM DISABLEDSYSAUX DISABLEDUNDOTBS1 DISABLEDTEMP DISABLEDUSERS DISABLEDUSERS01 ENABLED
启用前后执行计划的变化:
CREATE TABLE t_test( ordid number(12) primary key, cid varchar2(30), mid varchar2(10), oid varchar2(10), price number(22,6), vol number(13), direction char(1), offset char(1), userid varchar2(20), localid varchar2(20), vtotal number(13), vremain number(13), pricetype char(1)) ;
插入数据:
begin for i in 2001..12000 loop insert into t_test values(i,lpad(mod(i,100000),8,'0'),mod(i,200),mod(i,50),mod(i,2000000),mod(i,20000000),mod(i,2),mod(i,2),mod(i,500000),lpad(mod(i,10000),8,'0'),100,10,mod(i,2)); if mod(i,1000)=0 then commit ; end if ; end loop ;end ;
未启用IN MEMORY选项前的执行计划:
select count(distinct cid) ,sum(vol) from t_test ;COUNT(DISTINCTCID) COUNT(*) SUM(VOL)---------------------------- ---------- 2000 2000 2001000Execution Plan----------------------------------------------------------Plan hash value:766580343--------------------------------------------------------------------------------|Id | Operation |Name |Rows | Bytes | Cost (%CPU)| Time--------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | 43 | 8 (13) | 00:00:01| 1 | SORT AGGREGATE | | 1 | 43 | | | 2 | VIEW | VW_DAG_0 | 2000 | 86000 | 8 (13) | 00:00:01| 3 | HASH GROUP BY | | 2000 | 60000 | 8 (13) | 00:00:01| 4 | TABLE ACCESS FULL|T_TEST | 2000 | 60000 | 7 (0) | 00:00:01--------------------------------------------------------------------------------
启用表的IN MEMORY选项,并装载数据到IN MEMORY :
alter table t_test INMEMORY PRIORITY HIGH;SELECT /*+ FULL(p) NO_PARALLEL(p) */ COUNT(*) FROM t_test p;SELECT OWNER, SEGMENT_NAME, BYTES ORIG_SIZE, INMEMORY_SIZE IN_MEM_SIZE, ROUND (BYTES / INMEMORY_SIZE, 2)COMP_RATIOFROM V$IM_SEGMENTS ;OWNER SEGMENT_NAME ORIG_SIZE IN_MEM_SIZE COMP_RATIO------------------------ ---------- ----------- ----------TEST T_TEST 843776 1310720 .64
再次执行查看执行计划:
select count(distinct cid) ,sum(vol) from t_test ;COUNT(DISTINCTCID) SUM(VOL)---------------------------- 12000 72006000Execution Plan----------------------------------------------------------Plan hash value:766580343------------------------------------------------------------------------------------------| Id |Operation |Name | Rows | Bytes | Cost (%CPU)|Time |------------------------------------------------------------------------------------------| 0 | SELECTSTATEMENT | | 1 | 30 | 3 (34)| 00:00:01 || 1 | SORT AGGREGATE | | 1 | 30 | | || 2 | VIEW | VW_DAG_0 | 11351 | 332K| 3 (34) | 00:00:01 || 3 | HASH GROUP BY | | 11351 | 332K| 3 (34) | 00:00:01 || 4 | TABLE ACCESS INMEMORY FULL|T_TEST | 11351 | 332K| 2 (0) | 00:00:01 |
以上是Oracle In Memory的基本概念、如何设置和启用对数据库查询和操作的变化。IN Memory列存储模式,对数据库的开发操作无需做调整,但通过后台进程的透明处理,提供行存储和列存储两种数据模式,应对不同类型的数据库负载。后续继续对启用前后的性能变化,进一步描述IN MEMORY列存储模式的实际效果。
No.24。