天天看點

Oracle 12C In-Memory特性研究一、Oracle In-Memory二、In-Memory測試三、評估對象在IMO大小四、參考文獻

Oracle 12C In-Memory特性研究

  • 一、Oracle In-Memory
    • 1.1 In-Memory 開啟方法
    • 1.2 開啟與關閉IM column store
    • 1.3 inmemory優先級調整
    • 1.4 加載對象到IM
  • 二、In-Memory測試
    • 2.1 全字段查詢
    • 2.2 索引字段比較測試
    • 2.3 批量update測試
    • 2.4 大批量insert測試
    • 2.5 大量delete測試
    • 2.6 壓縮方式測試
    • 2.7 查詢大量列性能測試
  • 三、評估對象在IMO大小
  • 四、參考文獻

一、Oracle In-Memory

行格式與列格式:

Oracle 資料庫傳統上以行格式存儲資料。在行格式資料庫中,資料庫中存儲的每個新事務或新記錄都表示為表中的一個新行,而在查詢資料時是利用傳統BUFFER CACHE。

列格式資料庫将表以單獨的列結構存儲到記憶體中。列格式适用于報表類,分析,選擇少量列但是查詢要通路大部分的資料的場景。

Oracle 12C In-Memory特性研究一、Oracle In-Memory二、In-Memory測試三、評估對象在IMO大小四、參考文獻

1.1 In-Memory 開啟方法

啟用IMO非常簡單,12.1.0.2及之後版本下,設定INMEMORY_SIZE 為非0值便可啟用IM column store特性。

INMEMORY_SIZE 是個執行個體級參數,預設為0,設定一個非0值時,最小值為100M。

通常情況下,sys使用者下的對象及SYSTEM、SYSAUX表空間上的對象無法使用IMO特性,但通過設定“_enable_imc_sys”隐含參數也可以使用

開啟DB In-Memory過程如下:

1、修改INMEMORY_SIZE參數:

SQL> ALTER SYSTEM SET INMEMORY_SIZE=1G SCOPE=SPFILE;

2、檢查sga參數的設定,確定在設定完inmemroy_size參數之後資料庫執行個體還可以正常啟動。如果資料庫使用了ASMM,則需要檢查sga_target參數。如果使用了AMM,則需要檢查MEMORY_TARGET參數,同時也需要檢查SGA_MAX_TARGET(或MEMORY_MAX_TARGET)。

備注:從 12.2 開始,可以動态增加 In-Memory 區域的大小,為此,隻需 通過 ALTER SYSTEM 指令增加 INMEMORY_SIZE 參數值即可

3、重新開機資料庫執行個體

4、檢視IM特性是否開啟

SQL> SHOW PARAMETER inmemory;
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
inmemory_adg_enabled                 boolean     TRUE
inmemory_clause_default              string
inmemory_expressions_usage           string      ENABLE
inmemory_force                       string      DEFAULT
inmemory_max_populate_servers        integer     2
inmemory_query                       string      ENABLE
inmemory_size                        big integer 1G
inmemory_trickle_repopulate_servers_ integer     1
percent
inmemory_virtual_columns             string      MANUAL
optimizer_inmemory_aware             boolean     TRUE
           

1.2 開啟與關閉IM column store

1、TABLE 級啟用:

可以通過如下初始建表或後續修改表 inmemory 屬性的方式進行啟用:
create table test (id number) inmemory;
alter table test inmemory;
           

2、COLUMN 級啟用:

僅啟用表中某列前,該表必須先設定為 inmemory 模式:
alter table imo_t1 inmemory (id) no inmemory (name,type); alter table imo_t2 inmemory (name) no inmemory (id,type);

SELECT table_name, segment_column_id seg_col_id, column_name, inmemory_compression FROM v$im_column_level WHERE owner = 'IMOTEST' and table_name in ('IMO_T1','IMO_T2') ORDER BY 1,3;

                
TABLE_NAME SEG_COL_ID COLUMN_NAME   INMEMORY_COMPRESSION    
---------- ---------- --------------- -----------------------   
IMO_T1           1          ID          DEFAULT 
IMO_T1           2          NAME        NO INMEMORY 
IMO_T1           3          TYPE        NO INMEMORY 
IMO_T2           1          ID          NO INMEMORY 
IMO_T2           2          NAME        DEFAULT 
IMO_T2           3          TYPE        NO INMEMORY
           

3、表空間級啟用:

可以通過如下初始建立表空間或後續修改表空間 inmemory 屬性的方式進行啟用,在屬性為 inmemory 的表空間中建立的對象自動加載 inmemory 屬性,除非顯示設定對象為 no inmemory:
create tablespace imotest datafile '/u01/app/oracle/oradata/orcl/imotest01.dbf' size 100M default inmemory;

或
alter tablespace imotest default inmemory;
select tablespace_name, def_inmemory from dba_tablespaces where tablespace in ('IMOTEST');

TABLESPACE_NAME                 DEF_INMEMORY
------------------------------ ---------------
IMOTEST                         ENABLED
           

4、如果需要知道具體哪些列開啟了IM column store則需要到V$IM_COLUMN_LEVEL中進行檢視

5、查詢有關IM清單屬性

SQL> SELECT OWNER, SEGMENT_NAME,bytes,INMEMORY_SIZE,POPULATE_STATUS, BYTES_NOT_POPULATED FROM V$IM_SEGMENTS;

OWNER      SEGMENT_NA      BYTES INMEMORY_SIZE POPULATE_STAT BYTES_NOT_POPULATED
---------- ---------- ---------- ------------- ------------- -------------------
CS         MEM         391880704      52428800 COMPLETED                       0
CS         TEST         99426304      15138816 COMPLETED                       0
CS         DUP           5095424       3407872 COMPLETED                       0
           

6、關閉inmemory

1.3 inmemory優先級調整

啟用了 IMO 的對象,會按照一定的優先級進入 SGA 中配置好的 IN-MEMORY 區域,同時,在 IN-MEMORY 區域用滿後,依次置換出優先級較低的對象。下表為關于 IMO 對象優先級說明:

優先級描述

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
           

修改示例:

SQL> alter table test inmemory priority high;

SQL> col owner format a30

SQL> col segment_name format a30

SQL> SELECT INMEMORY,INMEMORY_PRIORITY,INMEMORY_COMPRESSION,INMEMORY_DISTRIBUTE, INMEMORY_DUPLICATE
FROM USER_TABLES WHERE TABLE_NAME = 'TEST';
INMEMORY INMEMORY INMEMORY_COMPRESS INMEMORY_DISTRI INMEMORY_DUPL
-------- -------- ----------------- --------------- -------------
ENABLED  HIGH     FOR QUERY LOW     AUTO            NO DUPLICATE
           

1.4 加載對象到IM

1、通過全表掃描objects加載資料到IM

SQL> SELECT /*+ FULL (s) */ COUNT(*) FROM table s;
查詢V$IM_SEGMENTS中的資料
SQL> col owner for a10

SQL> col SEGMENT_NAME for a10

SQL> SELECT OWNER, SEGMENT_NAME, POPULATE_STATUS, BYTES_NOT_POPULATED FROM V$IM_SEGMENTS;
 
OWNER      SEGMENT_NA POPULATE_ BYTES_NOT_POPULATED

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

CS    TEST      COMPLETED                   0
           

2、DBMS_INMEMORY來加載資料

DBMS_INMEMORY包提供了兩個PROCEDURE來手工加載資料到IM中:

POPULATE:強制加載給定的表

REPOPULATE:強制重新加載給定的表,在該表已經至少加載過一次之後才可使用。

手工執行DBMS_INMEMORY.POPULATE procedure來加載TEST表到IM中
SQL> EXEC DBMS_INMEMORY.POPULATE('CS','TEST');
           

通過DBMS_INMEMORY.REPOPULATE prcedure及FORCE=>TRUE選項來加載TEST表到IM中。FORCE=>TRUE選項強制進行一次完整重新載入,類似于full refresh

3、設定PRIORITY clause自動加載資料

将測試表TEST的PRIORITY級别改為HIGH。

二、In-Memory測試

2.1 全字段查詢

通過CTAS方式建立表TEST,普通行式掃描與開啟inmemory特性分别測試,比對執行計劃。

no inmemory查詢測試

set timing on
set autotrace traceonly
set pagesize 200 linesize 200
col TABLE_NAME for a20
col INMEMORY_PRIORITY for a20
col INMEMORY_DISTRIBUTE for a20
col INMEMORY_COMPRESSION for a20
           

全字段查詢,執行計劃

SQL> select count(*) from test;
COUNT(*)
----------
     74329
Elapsed: 00:00:00.01

Execution Plan
----------------------------------------------------------
Plan hash value: 1950795681

-------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Cost (%CPU)| Time     |
-------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |   403   (1)| 00:00:01 |
|   1 |  SORT AGGREGATE    |      |     1 |            |          |
|   2 |   TABLE ACCESS FULL| TEST | 74329 |   403   (1)| 00:00:01 |
-------------------------------------------------------------------


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

開啟in memory查詢測試

SQL> select TABLE_NAME,INMEMORY_PRIORITY,INMEMORY_DISTRIBUTE,INMEMORY_COMPRESSION from user_tables;

TABLE_NAME           INMEMORY_PRIORITY    INMEMORY_DISTRIBUTE  INMEMORY_COMPRESSION
-------------------- -------------------- -------------------- --------------------
TEST                 NONE                 AUTO                 FOR QUERY LOW

已開啟inmemory
           
SQL> select pool,ALLOC_BYTES/1024/1024,USED_BYTES/1024/1024,POPULATE_STATUS,con_id 
from V$INMEMORY_AREA;

POOL          ALLOC_BYTES/1024/1024 USED_BYTES/1024/1024 POPULATE_STATUS      CON_ID
------------  ------------          --------------------- ---------- ------------------
1MB POOL          815                    0                DONE                      3
64KB POOL         192                    0                DONE                      3
--因為隻是把該表設定了INMEMORY,但是未查詢過,是以查詢V$INMEMORY_AREA中未使用相關記憶體--
           

全字段查詢,執行計劃

第一次執行:

SQL> select count(*) from test;

  COUNT(*)
----------
     74329

Elapsed: 00:00:00.05

Execution Plan
----------------------------------------------------------
Plan hash value: 1950795681

----------------------------------------------------------------------------
| Id  | Operation                   | Name | Rows  | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |      |     1 |   403   (1)| 00:00:01 |
|   1 |  SORT AGGREGATE             |      |     1 |            |          |
|   2 |   TABLE ACCESS INMEMORY FULL| TEST | 74329 |   403   (1)| 00:00:01 |
----------------------------------------------------------------------------


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

第二次執行:

Elapsed: 00:00:00.03

Execution Plan
----------------------------------------------------------
Plan hash value: 1950795681

----------------------------------------------------------------------------
| Id  | Operation                   | Name | Rows  | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |      |     1 |    16   (7)| 00:00:01 |
|   1 |  SORT AGGREGATE             |      |     1 |            |          |
|   2 |   TABLE ACCESS INMEMORY FULL| TEST | 74329 |    16   (7)| 00:00:01 |
----------------------------------------------------------------------------


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

查詢inmemory記憶體使用:

SQL> select pool,ALLOC_BYTES/1024/1024,USED_BYTES/1024/1024,POPULATE_STATUS,con_id 
from V$INMEMORY_AREA;

POOL                       ALLOC_BYTES/1024/1024 USED_BYTES/1024/1024 POPULATE_STATUS                CON_ID
-------------------------- --------------------- -------------------- -------------------------- ----------
1MB POOL                                     815                    4 DONE                                3
64KB POOL                                    192                  .25 DONE                                3
--再次檢視,已經使用了配置設定的In-Memory中記憶體
           

性能比對:

sql plan no-inmemory inmemory
consistent gets 1460 9
physical reads
Cost 403 16

結果:

開啟inmemory之後性能提升162倍

2.2 索引字段比較測試

在已開啟IMO特性條件下,通過給表test增加列索引,比較IM與索引執行計劃

1、在object_name上建立索引

2、檢視表TEST是否加載到IM中

col owner for a20
col SEGMENT_NAME for a20
col POPULATE_STATUS for a20
col BYTES_NOT_POPULATED for 99999

SELECT OWNER, SEGMENT_NAME, POPULATE_STATUS, BYTES_NOT_POPULATED FROM V$IM_SEGMENTS;
OWNER                SEGMENT_NAME         POPULATE_STATUS      BYTES_NOT_POPULATED
-------------------- -------------------- -------------------- -------------------
CS                   TEST                 COMPLETED                              0
表已被加入到IM中
           

3、使用索引簡單列查詢

SQL> set autotrace traceonly
SQL> select count(*) from test where object_name='TEST';


Execution Plan
----------------------------------------------------------
Plan hash value: 3197243274

-------------------------------------------------------------------------------------
| Id  | Operation         | Name            | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |                 |     1 |    35 |     3   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE   |                 |     1 |    35 |            |          |
|*  2 |   INDEX RANGE SCAN| IDX_TEST_OBNAME |    10 |   350 |     3   (0)| 00:00:01 |
-------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("OBJECT_NAME"='TEST')


Statistics
----------------------------------------------------------
          2  recursive calls
          0  db block gets
          6  consistent gets
          2  physical reads
          0  redo size
        542  bytes sent via SQL*Net to client
        607  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
          
          邏輯讀:6
          實體:2
           

4、強制全表掃描查詢

SQL> select /*+full(s)*/count(*) from test s where object_name='test';

Execution Plan
----------------------------------------------------------
Plan hash value: 1950795681

------------------------------------------------------------------------------------
| Id  | Operation                   | Name | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |      |     1 |    35 |   124   (1)| 00:00:01 |
|   1 |  SORT AGGREGATE             |      |     1 |    35 |            |          |
|*  2 |   TABLE ACCESS INMEMORY FULL| TEST |     9 |   315 |   124   (1)| 00:00:01 |
------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - inmemory("OBJECT_NAME"='test')
       filter("OBJECT_NAME"='test')


Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
         10  consistent gets
          0  physical reads
          0  redo size
        541  bytes sent via SQL*Net to client
        607  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
          
邏輯讀:10
實體讀:0
           

總結:在資料離散度較高,且通過索引條件過濾的掃描場景中,IM特性對性能并沒有提升,傳統的索引+行式存儲的執行計劃已經足夠,在預設情況下還是會根據查詢索引傳回rowid的方式查找資料。

2.3 批量update測試

1、建立測試表disk、emp,分别為im表以及rows表,總數相同

SQL> create table disk as select * from dba_objects;
SQL> insert into disk select * from disk;

74360 rows created.

SQL> /

148720 rows created.

SQL> /

297440 rows created.

SQL> /

594880 rows created.

SQL> /

1189760 rows created.

SQL> commit;

Commit complete.

SQL> select count(*) from disk;

  COUNT(*)
----------
   2379520
   
  SQL> create table mem as select * from disk inmemory; 
           

更新磁盤表

update disk set owner=‘tom’;

更新記憶體表

update mem set owner=‘tom’;

普通表:

時間:14.49

邏輯讀:3202294+894128

實體讀:5602

cost:403

IM表:

時間:18.94

邏輯讀:3231179+254

實體讀:92476

cost:483

總結:IM特性在update性能有所下降

2.4 大批量insert測試

從磁盤插到磁盤

insert into disk select * from cs;

從磁盤插到記憶體

insert into mem select * from cs;

普通表:

時間:0.13

邏輯讀:9332+2903

實體讀:2895

cost:404

IM表:

時間:0.17

邏輯讀:3231179+254

實體讀:92476

cost:483

2.5 大量delete測試

delete from disk where rownum <10000;

delete from mem where rownum <10000;

普通表:

時間:0.08

邏輯讀:11470+202

實體讀:253

cost:12986

IM表:

時間:0.07

邏輯讀:11472+9

實體讀:0

cost:493

2.6 壓縮方式測試

壓縮方式 描述
NO MEMCOMPRESS IMO 中存儲無壓縮
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 預設設定、空間壓縮效果最優

檢視壓縮比

col owner for a5
col SEGMENT_NAME for a10
col POPULATE_STATUS for a10
col INMEMORY_COMPRESSION for a10
SQL> SELECT V.OWNER, V.SEGMENT_NAME,V.BYTES/1024/1024 ORIG_SIZE_MB,V.INMEMORY_SIZE/1024/1024 IN_MEM_SIZE_MB,BYTES_NOT_POPULATED,POPULATE_STATUS status,INMEMORY_COMPRESSION,V.BYTES/V.INMEMORY_SIZE COMP_RATIO FROM V$IM_SEGMENTS V WHERE SEGMENT_NAME = 'TEST';

    OWNER SEGMENT_NAME         ORIG_SIZE_MB IN_MEM_SIZE_MB BYTES_NOT_POPULATED STATUS               INMEMORY_COMPRESS COMP_RATIO
----- -------------------- ------------ -------------- ------------------- -------------------- ----------------- ----------
CS    TEST                   1466.78125        110.625                   0 COMPLETED            FOR QUERY LOW     13.2590395
           

表TEST在磁盤上占用1466MB,采用預設壓縮方式,記憶體中占用110.625MB,壓縮比為13.26:1

壓縮比測試:

表TEST大小1466.78125MB,資料行9514112

1、NO MEMCOMPRESS:

alter table test inmemory MEMCOMPRESS NO MEMCOMPRESS;
邏輯讀:14
實體讀:0
COST: 126
時間: 0.01
壓縮比:1.19
           

2、MEMCOMPRESS FOR DML:

alter table test inmemory MEMCOMPRESS FOR DML;
邏輯讀:14 
實體讀:0
COST: 126
時間:0.01
壓縮比:1.22
           

3、MEMCOMPRESS FOR QUERY LOW:

alter table test inmemory MEMCOMPRESS FOR QUERY LOW;
邏輯讀:14
實體讀:0
COST:125
時間:0.01
壓縮比:7.20
           

4、MEMCOMPRESS FOR QUERY HIGH:

alter table test inmemory MEMCOMPRESS FOR QUERY high;
邏輯讀:14
實體讀:0
COST: 125
時間:0.01
壓縮比:9.67
           

5、MEMCOMPRESS FOR CAPACITY LOW:

alter table test inmemory MEMCOMPRESS FOR CAPACITY LOW;
邏輯讀:14
實體讀:0
COST: 125
時間:0.01
壓縮比:12.91
           

6、MEMCOMPRESS FOR CAPACITY HIGH:

alter table test inmemory MEMCOMPRESS FOR CAPACITY HIGH;
邏輯讀:14
實體讀:0
COST: 25
時間:0.01
壓縮比:19.14

           

測試結果彙總:

壓縮方式 壓縮比
NO MEMCOMPRESS 1.19
MEMCOMPRESS FOR DML 1.22
MEMCOMPRESS FOR QUERY LOW 7.20
MEMCOMPRESS FOR QUERY HIGH 9.67
MEMCOMPRESS FOR CAPACITY LOW 12.91
MEMCOMPRESS FOR CAPACITY HIGH 19.14

總結:壓縮方式不同,表加載到IM中的時間也會不一樣。壓縮比越大加載到記憶體中的時間越長。而對于select查詢消耗時間不影響。

2.7 查詢大量列性能測試

三、評估對象在IMO大小

DBMS_COMPRESSION.GET_COMPRESSION_RATIO

在對一張表使用COMPRESSION clause進行IM壓縮級别設定之前,我們可以通過Oracle的COMPRESSION ADVISOR對表放入到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 => 'CS',

ownname => 'CS',

objname => 'TEST',

subobjname => NULL,

comptype => dbms_compression.comp_inmemory_QUERY_LOW,

-- 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 LOW):'||l_cmp_ratio);

END;

/
           

Comp. ratio (QUERY LOW):7

估計結果壓縮比7,實際壓縮比為7.20

#五、RAC環境測試

rac環境獨有參數DUPLICATE clause、DISTRIBUTE clause:

DUPLICATE clause:

此參數為EXADATA一體機專用,在RAC環境中,每個節點擁有自己的IM Area。一個objects根據DUPLICATE clause的設定将一樣的資料加載到多個IM Area中。

預設是NO DUPLICATE設定,表示在資料庫的IM中對一個objects在所有節點中合起來隻儲存一份。舉例說明,比如三節點的RAC中,對于分區表SALES來講可能2012年份的資料在1節點,2013年份的資料在2節點,2014年份的資料在3節點,每個分區隻儲存在一個節點上。

為了提升可用性,也可以設定為DUPLICAET ALL,在每個節點上都儲存一份。舉例說明,還是剛才那個SALES表的請款下,1,2,3三個節點各儲存一份完整sales表資料到各自的IM中。在任意一個節點上都可以擷取查詢需要的資料。

在設定為DUPLICATE ALL的情況下

DISTRIBUTE clause:

如果一個objects因為太大無法被加載到一個IM Area中,還可以通過DISTRIBUTE clause的設定将它分成幾個資料片分别加載到不同的節點中。

預設情況下DISTRIBUTE clause的預設值為AUTO-DISTRIBUTE,這時候是否将objects分布式分布在不同的節點上由Oracle内部算法決定。這個參數對于單執行個體沒有影響,在RAC環境中,預設存在IM中的表會分布在各個節點之中。

RAC環境并不像單執行個體一樣隻需修改表的IM屬性即可啟用,如果要使用IMO,必須在系統層面修改“并行度政策”為自動。下面對參數“parallel_degree_policy”,分别測試2個場景

1、先檢視要測試的表TEST是否已加載到IM STORE

col SEGMENT_NAME for a5
col POPULATE_STATUS for a10
col INMEMORY_DISTRIBUTE for a10
col INMEMORY_DUPLICATE for a20

SQL> select INST_ID,SEGMENT_NAME,INMEMORY_SIZE/1024/1024,BYTES/1024/1024,BYTES_NOT_POPULATED/1024/1024,INMEMORY_DISTRIBUTE,INMEMORY_DUPLICATE,POPULATE_STATUS from gv$im_segments;

   INST_ID SEGME INMEMORY_SIZE/1024/1024 BYTES/1024/1024 BYTES_NOT_POPULATED/1024/1024 INMEMORY_D INMEMORY_DUPLICATE   POPULATE_S
---------- ----- ----------------------- --------------- ----------------------------- ---------- -------------------- ----------
         2 TEST                    9.125             192                     123.53125 AUTO       NO DUPLICATE         COMPLETED
         1 TEST                  16.1875             192                    66.9140625 AUTO       NO DUPLICATE         COMPLETED
           

1、開啟AUTO DOP

alter system set parallel_degree_policy=AUTO sid='*';
alter system set parallel_force_local=false sid='*';
alter system flush buffer_cache;
alter system flush shared_pool;
           

2、檢視執行計劃

SQL> select /*+ parallel */count(*) from test;

  COUNT(*)
----------
   1455168


Execution Plan
----------------------------------------------------------
Plan hash value: 2661943167

-----------------------------------------------------------------------------------------------------------------
| Id  | Operation                       | Name     | Rows  | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
-----------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                |          |     1 |     9   (0)| 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          |          | 90948 |     9   (0)| 00:00:01 |  Q1,00 | PCWC |            |
|   6 |       TABLE ACCESS INMEMORY FULL| TEST     | 90948 |     9   (0)| 00:00:01 |  Q1,00 | PCWP |            |
-----------------------------------------------------------------------------------------------------------------

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


Statistics
----------------------------------------------------------
        232  recursive calls
          4  db block gets
        163  consistent gets
         15  physical reads
          0  redo size
        545  bytes sent via SQL*Net to client
        551  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
         16  sorts (memory)
          0  sorts (disk)
          1  rows processed   
           
邏輯讀:163
實體讀:15
           

3、不使用并行查詢查詢

SQL> select count(*) from test;

  COUNT(*)
----------
   1455168


Execution Plan
----------------------------------------------------------
Plan hash value: 1950795681

----------------------------------------------------------------------------
| Id  | Operation                   | Name | Rows  | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |      |     1 |    16   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE             |      |     1 |            |          |
|   2 |   TABLE ACCESS INMEMORY FULL| TEST | 90948 |    16   (0)| 00:00:01 |
----------------------------------------------------------------------------

Note
-----
   - automatic DOP: Computed Degree of Parallelism is 1 because of no expensive parallel operation


Statistics
----------------------------------------------------------
          3  recursive calls
          0  db block gets
       9081  consistent gets
       9077  physical reads
          0  redo size
        545  bytes sent via SQL*Net to client
        551  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
           
邏輯讀:9081
實體讀:9077
           

4、關閉AUTO DOP

alter system set parallel_degree_policy=MANUAL sid='*';
alter system set parallel_force_local=false sid='*';
alter system flush buffer_cache;
alter system flush shared_pool;
           

5、檢視執行計劃

SQL> select /*+ parallel */count(*) from test;

  COUNT(*)
----------
   1455168


Execution Plan
----------------------------------------------------------
Plan hash value: 2661943167

-----------------------------------------------------------------------------------------------------------------
| Id  | Operation                       | Name     | Rows  | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
-----------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                |          |     1 |     9   (0)| 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          |          | 90948 |     9   (0)| 00:00:01 |  Q1,00 | PCWC |            |
|   6 |       TABLE ACCESS INMEMORY FULL| TEST     | 90948 |     9   (0)| 00:00:01 |  Q1,00 | PCWP |            |
-----------------------------------------------------------------------------------------------------------------

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


Statistics
----------------------------------------------------------
        209  recursive calls
          4  db block gets
      17909  consistent gets
      17766  physical reads
          0  redo size
        545  bytes sent via SQL*Net to client
        551  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
         16  sorts (memory)
          0  sorts (disk)
          1  rows processed
           
邏輯讀:17909
    實體讀:17766
           

總結:

1、調整系統參數(parallel_degree_policy)之後,rac環境下的IM列查詢大幅降低了邏輯讀與實體讀。

2、在多執行個體的并發查詢中執行個體之間傳輸的并不是IMCU,而是每個節點都會對本節點的資料運作相同的sql語句,之後把自己的結果集發送給發起sql語句的執行個體,組成最終的結果傳回給使用者。

parallel_degree_policy AUTO MANUAL
邏輯讀 163 17909
實體讀 15 17766

備注:

在沒有顯式使用并行sql時,rac環境im全表掃描并沒有使用并行。oracle的優化器會通過一系列的計算比較cost。

SQL> select count(*) from test;
執行計劃Note
-----
automatic DOP: 
Computed Degree of Parallelism is 1 because of no expensive parallel operation
           

In some cases, even with Auto DOP set correctly, the optimizer may calculate the cost of a serial access to be less than the cost of a parallel access. This has been identified as bug 18960760, and will usually only happen when very smalltables in the IM column store are involved in the query.

來自Oracle Blog
https://blogs.oracle.com/in-memory/oracle-database-in-memory-on-rac-part-i
           

四、參考文獻

1、Oracle Database In-Memory on RAC - Part I

https://blogs.oracle.com/in-memory/oracle-database-in-memory-on-rac-part-i

2、Oracle 12c DB In-Memory入門實驗手冊

https://blog.csdn.net/badly9/article/details/49777993

3、Oracle12c IMO 測試

https://www.jianshu.com/p/966ee0182e1c

4、rac并行查詢

http://blog.sina.com.cn/s/blog_74a7d3390102wegl.html

5、Oracle In-Memory白皮書

http://www.oracle.com/technetwork/cn/database/in-memory/overview/twp-oracle-database-in-memory-2245633-zhs.pdf

繼續閱讀