当前位置: 首页 > Oracle, Oracle 12c, Oracle 19c > 正文

Oracle 12c in memory新特性

今天,简单学习一下Oracle 12c(12.1.0.2)推出的IN-MEMORY新特性,早上发生点不愉快的事情,有点闹心,可能整理的不是很全面。我的实验环境是一个2节点的RAC,操作系统版本是OEL 7.6,数据库版本是19.3.0.0.0。

IN-MEMORY特性会在SGA中单独分配一个INMEMORY_AREA区域,把全表、个别分区或者个别列以压缩或者不压缩并且以列存储的模式保存到INMEMORY_AREA区,可以极大提高对大量数据的分析。

默认情况下,SYSTEM和SYSAUX表空间里面的对象是不能使用IN_MEMORY特性的,但是可用通过修改_enable_imc_sys隐含参数的设置来控制SYSTEM和SYSAUX表空间里面的对象也可用使用这个特性,基本用不到。

启用INMEMORY_AREA特性,需要调整inmemory_size和inmemory_max_populate_servers两个参数。

SQL> show parameter inmem

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
inmemory_adg_enabled                 boolean     TRUE
inmemory_automatic_level             string      OFF
inmemory_clause_default              string
inmemory_expressions_usage           string      ENABLE
inmemory_force                       string      DEFAULT
inmemory_max_populate_servers        integer     0
inmemory_optimized_arithmetic        string      DISABLE
inmemory_prefer_xmem_memcompress     string
inmemory_prefer_xmem_priority        string
inmemory_query                       string      ENABLE
inmemory_size                        big integer 0
inmemory_trickle_repopulate_servers_ integer     1
percent
inmemory_virtual_columns             string      MANUAL
inmemory_xmem_size                   big integer 0
optimizer_inmemory_aware             boolean     TRUE

其实只设置inmemory_size参数也可以,inmemory_size参数是指在SGA中分配的INMEMORY_AREA区域的大小,最小值是100MB。这个参数在12.1.0.2版本是个静态参数,调整后需要重启才能生效,在12.2版本开始,这个参数可以动态调整,但是新启动的情况下,也就是从0调整到100MB以上时,还是不能动态调整,必须重启才能生效。分解演示如下:

SQL> alter system set inmemory_size=1G sid='*';
alter system set inmemory_size=1G sid='*'
*
ERROR at line 1:
ORA-02097: parameter cannot be modified because specified value is invalid
ORA-02095: specified initialization parameter cannot be modified

直接从0调整inmemory_size参数失败,不能直接启用,需要修改参数文件,然后重启生效。

SQL> alter system set inmemory_size=1G scope=spfile sid='*';

System altered.
SQL> startup force
ORACLE instance started.

Total System Global Area 4.1876E+10 bytes
Fixed Size                 30141128 bytes
Variable Size            6845104128 bytes
Database Buffers         3.3823E+10 bytes
Redo Buffers              104075264 bytes
In-Memory Area           1073741824 bytes
Database mounted.
Database opened.

加上SCOPE=SPFILE,在参数文件中修改inmemory_size参数,重启数据库参数设置成功。

SQL> alter system set inmemory_size=15G sid='*';

System altered.

之后,inmemory_size参数可用动态调整,即时生效。

SQL> show sga

Total System Global Area 4.1876E+10 bytes
Fixed Size                 30141128 bytes
Variable Size            7247757312 bytes
Database Buffers         1.8388E+10 bytes
Redo Buffers              104075264 bytes
In-Memory Area           1.6106E+10 bytes

会根据inmemory_size参数的设置在SGA中分配In-Memory Area区域,inmemory_size参数大小视情况而定,分配过大会浪费内存资源,分配过小会导致数据不能全部加载到In-Memory Area区域,v$im_segments视图的POPULATE_STATUS字段会遇到OUT OF MEMORY的情况,但是不影响对表的操作,只是加速没那么彻底。

inmemory_max_populate_servers参数是控制populate_servers的个数,populate是用来将数据从硬盘加载到INMEMORY_AREA区的操作,数量默认是CPU_COUNT数的一半,populate_servers数量越多,加载的速度越快,资源消耗也越多,我这里设置为2个。这个参数是动态参数,可以直接设置,即时生效。

SQL> alter system set inmemory_max_populate_servers=2 sid='*';

System altered.

下面创建一张测试表,T_TEXT_IM,大小约12.5GB,大概1亿条记录。

SQL> conn dbdream/dbdream
Connected.
SQL> select segment_name,bytes/1024/1024/1024 GB from user_segments;

SEGMENT_NAME            GB
--------------- ----------
T_TEXT_BASIC          12.5
SQL> create table t_text_im as select * from T_TEXT_BASIC;

Table created.
SQL> select segment_name,bytes/1024/1024/1024 GB from user_segments;

SEGMENT_NAME            GB
--------------- ----------
T_TEXT_BASIC          12.5
T_TEXT_IM       12.5517578

这样就可以使用IN_MEMORY特性了,在做测试之前,先说一下populate的优先级,也就是什么时候把数据倒腾到内存中。

PRIORITY NONE:默认值;执行 SQL 引起对象扫描后,触发进入 IN-MEMORY
PRIORITY CRITICAL:最高优先级;立即进入 IN-MEMORY
PRIORITY HIGH:在具有 CRITICAL 优先级的对象之后进入 IN-MEMORY
PRIORITY MEDIUM:在具有 CRITICAL、HIGH 优先级的对象之后进入 IN-MEMORY
PRIORITY LOW:在具有 CRITICAL、HIGH、MEDIUM 优先级的对象之后进入 IN-MEMORY

如果在使用IN_MEMORY特性的时候不指定PRIORITY的级别,默认使用PRIORITY NONE,需要有SQL扫描那个表之后触发加载进程。

在看一下压缩方式。

NO MEMCOMPRESS:不压缩
MEMCOMPRESS FOR DML:最小化压缩,优化 DML 操作
MEMCOMPRESS FOR QUERY LOW:默认值:查询性能最优、空间压缩效果好于DML方式
MEMCOMPRESS FOR QUERY HIGH:查询性能次优(excellent)、空间压缩效果好于 QUERY LOW
MEMCOMPRESS FOR CAPACITY LOW:查询性能良好(good)、空间压缩效果好于 QUERY HIGH
MEMCOMPRESS FOR CAPACITY HIGH:空间压缩效果最优

如果不知道压缩方式,默认使用MEMCOMPRESS FOR QUERY LOW的压缩方式。

对RAC数据库来讲,还有一个数据分布方式需要说一下。有DISTRIBUTE和DUPLICATE两种数据分布方式。

DISTRIBUTE是默认的分布方式,是把数据分片存放到RAC的各个实例上,可以按照DISTRIBUTE BY ROWID RANGE 按 rowid 范围分布,指定 DISTRIBUTE BY PARTITION 将分区分布给不同的节点,或指定 DISTRIBUTE BY SUBPARTITION 将子分区分布给不同的节点,如果不指定,默认使用AUTO分布方式。

DUPLICATE的分布方式,是把整份数据存放在RAC的各个节点的实例中,可用指定具体节点,也可用是所有节点,也就是各个节点都存一份完整一样的数据,而不是每个节点只存部分数据。这对内存要求比较高。我参考的文档里说DUPLICATE的分布方式是EXADATA一体机专属的功能,但我用的19.3版本也可用用。

拿喝酒打个比方,DISTRIBUTE的分布方式类似于上海人喝酒,一桌人分着喝一瓶酒,每个人都喝一点;DUPLICATE就好比东北人喝酒,必须一人喝一瓶,当然有酒精过敏的可用不喝。比喻不太恰当,没有地域歧视,莫要误会。

下面把测试表开启IN_MEMORY功能。

SQL> alter table dbdream.T_TEXT_IM inmemory PRIORITY CRITICAL;

Table altered.

有几个IN_MEMORY相关的视图可用查看相关的信息。V$INMEMORY_AREA、V$IM_SEGMENTS、V$IM_COLUMN_LEVEL,RAC数据库需要查询GV$相关的视图。

SQL> select OWNER,SEGMENT_NAME,INMEMORY_SIZE/1024/1024/1024 im_size_gb,BYTES/1024/1024/1024 GB,BYTES_NOT_POPULATED/1024/1024/1024 BNP,POPULATE_STATUS,INMEMORY_PRIORITY,INMEMORY_DISTRIBUTE,INMEMORY_DUPLICATE,INMEMORY_COMPRESSION,INMEMORY_SERVICE from GV$IM_SEGMENTS;

OWNER           SEGMENT_NAME    IM_SIZE_GB         GB        BNP POPULATE_STAT INMEMORY INMEMORY_DISTRI INMEMORY_DUPL INMEMORY_COMPRESS INMEMORY_SER
--------------- --------------- ---------- ---------- ---------- ------------- -------- --------------- ------------- ----------------- ------------
DBDREAM         T_TEXT_IM       .051330566 12.4903259 12.1038666 STARTED       CRITICAL AUTO            NO DUPLICATE  FOR QUERY LOW     DEFAULT
DBDREAM         T_TEXT_IM       .018371582 12.4903259 12.3500366 STARTED       CRITICAL AUTO            NO DUPLICATE  FOR QUERY LOW     DEFAULT

V$IM_SEGMENTS视图的POPULATE_STATUS字段代表的是从硬盘把数据倒腾到内存的状态,STARTED是进程已经启动,正在干;COMPLETED状态是这个活已经干完了。

下面看一下全表扫描的执行计划。

SQL> SELECT COUNT(*) FROM DBDREAM.T_TEXT_IM;

  COUNT(*)
----------
  97558528

Execution Plan
----------------------------------------------------------
Plan hash value: 2936459351

---------------------------------------------------------------------------------
| Id  | Operation                   | Name      | Rows  | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |           |     1 | 16925   (3)| 00:00:01 |
|   1 |  SORT AGGREGATE             |           |     1 |            |          |
|   2 |   TABLE ACCESS INMEMORY FULL| T_TEXT_IM |    97M| 16925   (3)| 00:00:01 |
---------------------------------------------------------------------------------

Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
     846669  consistent gets
          0  physical reads
          0  redo size
        553  bytes sent via SQL*Net to client
        400  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

逻辑读846669,在看一下不使用IN_MEMORY特性时的全表扫的执行计划。

SQL> SELECT /*+no_inmemory*/ COUNT(*) FROM DBDREAM.T_TEXT_IM;

  COUNT(*)
----------
  97558528

Execution Plan
----------------------------------------------------------
Plan hash value: 1663429650

------------------------------------------------------------------------
| Id  | Operation          | Name      | Rows  | Cost (%CPU)| Time     |
------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |           |     1 |   444K  (1)| 00:00:18 |
|   1 |  SORT AGGREGATE    |           |     1 |            |          |
|   2 |   TABLE ACCESS FULL| T_TEXT_IM |    97M|   444K  (1)| 00:00:18 |
------------------------------------------------------------------------

Statistics
----------------------------------------------------------
         30  recursive calls
          0  db block gets
    1642772  consistent gets
          0  physical reads
          0  redo size
        553  bytes sent via SQL*Net to client
        417  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

逻辑读1642772。

使用IN_MEMORY时,逻辑读846669,不使用IN_MEMORY时,逻辑读1642772,好像使用IN_MEMORY逻辑读只减少了一半,效果不是特别明显,这又要说一下parallel_degree_policy并行的问题,RAC数据库IN_MEMORY和并行配合使用,效果才会特别明显。

SQL> alter system set parallel_degree_policy=auto sid='*';

System altered.

SQL> SELECT COUNT(*) FROM DBDREAM.T_TEXT_IM;

  COUNT(*)
----------
  97558528

Execution Plan
----------------------------------------------------------
Plan hash value: 1663429650

-----------------------------------------------------------------------------------------------------------------
| Id| Operation                      | Name      | Rows  | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
-----------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT                |           |     1 |   324   (3)| 00:00:01 |        |      |            |
| 1 |  SORT AGGREGATE                 |           |     1 |            |          |        |      |            |
| 2 |   PX COORDINATOR                |           |       |            |          |        |      |            |
| 3 |    PX SEND QC (RANDOM)          | :TQ10000  |     1 |            |          |  Q1,00 | P->S | QC (RAND)  |
| 4 |     SORT AGGREGATE              |           |     1 |            |          |  Q1,00 | PCWP |            |
| 5 |      PX BLOCK ITERATOR          |           |    97M|   324   (3)| 00:00:01 |  Q1,00 | PCWC |            |
| 6 |       TABLE ACCESS INMEMORY FULL| T_TEXT_IM |    97M|   324   (3)| 00:00:01 |  Q1,00 | PCWP |            |
-----------------------------------------------------------------------------------------------------------------

Note
-----
   - automatic DOP: Computed Degree of Parallelism is 58
   - parallel scans affinitized for inmemory

Statistics
----------------------------------------------------------
        316  recursive calls
          8  db block gets
        608  consistent gets
          0  physical reads
          0  redo size
        553  bytes sent via SQL*Net to client
        400  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          5  sorts (memory)
          0  sorts (disk)
          1  rows processed

再测一下DUPLICATE的分布方式,我参考的资料说是EXADATA的专属功能,但我在19.3版本上测试也可用使用,其他版本是否可用使用就不清楚了。

SQL> alter table dbdream.T_TEXT_IM no inmemory;

Table altered.
SQL> alter table dbdream.T_TEXT_IM inmemory DUPLICATE all PRIORITY CRITICAL;

Table altered.
SQL> select OWNER,SEGMENT_NAME,INMEMORY_SIZE/1024/1024/1024 im_size_gb,BYTES/1024/1024/1024 GB,BYTES_NOT_POPULATED/1024/1024/1024 BNP,POPULATE_STATUS,INMEMORY_PRIORITY,INMEMORY_DISTRIBUTE,INMEMORY_DUPLICATE,INMEMORY_COMPRESSION,INMEMORY_SERVICE from gv$im_segments;

OWNER           SEGMENT_NAME    IM_SIZE_GB         GB        BNP POPULATE_STAT INMEMORY INMEMORY_DISTRI INMEMORY_DUPL INMEMORY_COMPRESS INMEMORY_SER
--------------- --------------- ---------- ---------- ---------- ------------- -------- --------------- ------------- ----------------- ------------
DBDREAM         T_TEXT_IM       .051330566 12.4903259 12.1038666 STARTED       CRITICAL AUTO            DUPLICATE ALL FOR QUERY LOW     DEFAULT
DBDREAM         T_TEXT_IM       .018371582 12.4903259 12.3500366 STARTED       CRITICAL AUTO            DUPLICATE ALL FOR QUERY LOW     DEFAULT
SQL> /

OWNER           SEGMENT_NAME    IM_SIZE_GB         GB        BNP POPULATE_STAT INMEMORY INMEMORY_DISTRI INMEMORY_DUPL INMEMORY_COMPRESS INMEMORY_SER
--------------- --------------- ---------- ---------- ---------- ------------- -------- --------------- ------------- ----------------- ------------
DBDREAM         T_TEXT_IM       .868408203 12.4903259 5.73591614 COMPLETED     CRITICAL AUTO            DUPLICATE ALL FOR QUERY LOW     DEFAULT
DBDREAM         T_TEXT_IM       .735778809 12.4903259 6.75440979 COMPLETED     CRITICAL AUTO            DUPLICATE ALL FOR QUERY LOW     DEFAULT
SQL> select count(*) from DBDREAM.T_TEXT_IM;

  COUNT(*)
----------
  97558528

Execution Plan
----------------------------------------------------------
Plan hash value: 1663429650

-----------------------------------------------------------------------------------------------------------------
| Id| Operation                       | Name      | Rows  | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
-----------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT                |           |     1 |   324   (3)| 00:00:01 |        |      |            |
| 1 |  SORT AGGREGATE                 |           |     1 |            |          |        |      |            |
| 2 |   PX COORDINATOR                |           |       |            |          |        |      |            |
| 3 |    PX SEND QC (RANDOM)          | :TQ10000  |     1 |            |          |  Q1,00 | P->S | QC (RAND)  |
| 4 |     SORT AGGREGATE              |           |     1 |            |          |  Q1,00 | PCWP |            |
| 5 |      PX BLOCK ITERATOR          |           |    97M|   324   (3)| 00:00:01 |  Q1,00 | PCWC |            |
| 6 |       TABLE ACCESS INMEMORY FULL| T_TEXT_IM |    97M|   324   (3)| 00:00:01 |  Q1,00 | PCWP |            |
-----------------------------------------------------------------------------------------------------------------

Note
-----
   - automatic DOP: Computed Degree of Parallelism is 58
   - parallel scans affinitized for inmemory

Statistics
----------------------------------------------------------
        242  recursive calls
          8  db block gets
        612  consistent gets
          0  physical reads
          0  redo size
        553  bytes sent via SQL*Net to client
        400  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          7  sorts (memory)
          0  sorts (disk)
          1  rows processed

参考文献:

https://www.cnblogs.com/fyy-hhzzj/p/9083456.html

http://www.pianshen.com/article/2447218719/

 

本文固定链接: https://www.dbdream.com.cn/2019/06/oracle-12c-in-memory%e6%96%b0%e7%89%b9%e6%80%a7/ | 信春哥,系统稳,闭眼上线不回滚!

该日志由 dbdream 于2019年06月19日发表在 Oracle, Oracle 12c, Oracle 19c 分类下, 你可以发表评论,并在保留原文地址及作者的情况下引用到你的网站或博客。
原创文章转载请注明: Oracle 12c in memory新特性 | 信春哥,系统稳,闭眼上线不回滚!
关键字: , ,

Oracle 12c in memory新特性:等您坐沙发呢!

发表评论

快捷键:Ctrl+Enter