12c in memory option學習筆記一_基礎篇
Oracle 12c in memory選件透過在SGA中分配獨立的記憶體區域(In Memory Area),對資料使用列式壓縮儲存來提高查詢效能.
In Memory區的大小由引數inmemory_size控制, 該引數是一個靜態引數, 修改後需要重啟資料庫方可生效.
In Memory記憶體區可分為兩個子池,分別為1M pool和64K pool. 1M pool用於儲存列式資料. 64K pool用於儲存物件的後設資料(metadata)和事務日誌(transaction journal). 1M pool 中分配的記憶體塊的大小為1M的整數倍,64K pool中分配的記憶體塊大小均為64K。
v$inmemory_area檢視有每個pool大小的詳細資訊:
SQL> select * from v$inmemory_area;
POOL ALLOC_BYTES USED_BYTES POPULATE_STATUS CON_ID
-------------------------- ----------- ---------- -------------------------- ----------
1MB POOL 854589440 10485760 DONE 0
64KB POOL 201326592 393216 DONE 0
In Memory區的資料裝載(populating)
相對於磁碟或者快閃記憶體,記憶體資源畢竟成本更高,更為有限,所以需要將有限的資源分配給更需要的物件. Oracle新增了一個INMEMORY屬性用於控制物件是否會被裝載到In Memory區, 該屬性可以定義在表 空間,表,分割槽甚至列級. Oracle In Memory白皮書中給出了一些設定物件IMMEMORY屬性的具體用例, 摘錄於此, 以備將來參考:
ALTER TABLESPACE ts_data INMEMORY;
ALTER TABLE sales INMEMORY NO INMEMORY(prod_id);
ALTER TABLE sales MODIFY PARTITION SALES_Q1_1998 NO INMEMORY;
此外,為了控制物件的裝載順序,Oracle定義了5種優先順序來實現精細控制,透過priority子句來選擇.詳細資訊如下:
根據自己的需求,可以選擇以上幾種優先順序中的一種來定義該物件的裝載順序.若未指定priority子句,則其預設值為NONE.
IM物件的裝載是由後臺程式ora_w00*_<sid>完成的.引數inmemory_max_populate_servers控制IM後臺裝載程式的個數, 其預設值為cpu_count的一半. 程式數越多,裝載速度越快,但消耗的資源也更多.
注:實際觀察發現inmemory_max_populate_servers引數並不是對後臺裝載程式ora_w00*_<sid>的硬性限制,它更像是一個最小值的設定,因為實際中發現ora_w00*_<sid>程式數是可以動態增加的。
在物件載入In Memory區後, 可使用no inmemory操作將其從IM區清除
alter table TEST_IM no inmemory;
此外,要注意的是,改變原有的priority(或者memcompress)屬性,也會導致該物件被清除出IM區.比如:
alter table TEST_IM inmemory priority critical; --原值為none
這裡還要注意的一點是,由於儲存資料塊的大小為1M的整數倍,也就是記憶體分配的最小單位是1M,為了避免空間浪費,Oracle不會將<=64K大小的物件載入In Memory區.這裡做個簡單測試來驗證這一點:
create table test_im(v varchar2(100)) inmemory pctused 1 pctfree 99 tablespace users;
insert into test_im select rpad('a',100,'a') from dual connect by level <=5;
commit;
SQL> select bytes/1024 from dba_segments where segment_name='TEST_IM';
BYTES/1024
----------
64
SQL> select * from TEST_IM;
……
SQL> select * from v$im_segments where segment_name='TEST_IM';
no rows selected
查詢v$im_segments可發現表TEST_IM並不在IM區.
SQL> insert into test_im select rpad('a',100,'a') from dual;
1 row created.
SQL> commit;
Commit complete.
SQL> select bytes/1024 from dba_segments where segment_name='TEST_IM';
BYTES/1024
----------
128
SQL> select * from TEST_IM;
……
SQL> select SEGMENT_NAME,INMEMORY_SIZE,BYTES,POPULATE_STATUS from v$im_segments where segment_name='TEST_IM';
SEGMENT_NAME INMEMORY_SIZE BYTES POPULATE_STATUS
-------------------- ------------- ---------- --------------------
TEST_IM 1179648 131072 COMPLETED
而當表TEST_IM的大小大於64K時,Oracle才會將其裝載入In Memory區.
In Memory壓縮
Oracle為IM中的物件提供了六種級別的壓縮選項, 可透過MEMCOMPRESS子句來指定, 詳細資訊如下:
透過下例來觀察In Memory列壓縮功能:
SQL> create table test_im_comp tablespace users as select * from dba_objects;
Table created.
SQL> insert into test_im_comp select * from test_im_comp;
92203 rows created.
SQL> /
……
SQL> commit;
Commit complete.
SQL> alter table TEST_IM_COMP inmemory memcompress for query low;
SQL> select count(*) from test_im_comp;
COUNT(*)
----------
2950496
之後可以看到開始向In Memory區裝載TEST_IM_COMP表:
select SEGMENT_NAME,INMEMORY_SIZE,BYTES,POPULATE_STATUS from v$im_segments;
SEGMENT_NAME INMEMORY_SIZE BYTES POPULATE_
------------------------------ ------------- ---------- ---------
TEST_IM_COMP 6553600 411041792 STARTED
等待一會, TEST_IM_COMP表裝載完畢,從壓縮前後的大小比對可看出,這裡採用“memcompress for query low”壓縮演算法後TEST_IM_COMP表的壓縮比大約為6:1。
SQL> select SEGMENT_NAME,INMEMORY_SIZE,BYTES,POPULATE_STATUS from v$im_segments;
SEGMENT_NAME INMEMORY_SIZE BYTES POPULATE_
------------------------------ ------------- ---------- ---------
TEST_IM_COMP 63373312 411041792 COMPLETED
透過使用dbms_compression包,也可以預估資料庫物件在採用不同壓縮級別後載入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);
comp_ratio_allrows NUMBER := -1;
BEGIN
dbms_compression.get_compression_ratio (
scratchtbsname => 'USERS',
ownname => 'SYS',
objname => 'TEST_IM_COMP',
subobjname => NULL,
comptype => dbms_compression.comp_inmemory_query_low, --該引數控制壓縮級別
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('The IM compression ratio is '|| l_cmp_ratio);
END;
/
The IM compression ratio is 6
上述指令碼中的comptype選項可從dbmscomp.sql指令碼中獲得,如下:
grep -i comp_inmemory $ORACLE_HOME/rdbms/admin/dbmscomp.sql
COMP_INMEMORY_NOCOMPRESS CONSTANT NUMBER := 8192;
COMP_INMEMORY_DML CONSTANT NUMBER := 16384;
COMP_INMEMORY_QUERY_LOW CONSTANT NUMBER := 32768;
COMP_INMEMORY_QUERY_HIGH CONSTANT NUMBER := 65536;
COMP_INMEMORY_CAPACITY_LOW CONSTANT NUMBER := 131072;
COMP_INMEMORY_CAPACITY_HIGH CONSTANT NUMBER := 262144;
在以上Oracle提供的5種壓縮演算法中,FOR QUERY LOW選項壓縮後的資料查詢效能最佳。它使用的是一些常規的壓縮技術,如“Dictionary Encoding, Run Length Encoding and Bit-Packing”.
其他壓縮技術的壓縮比例更高,但隨之帶來的讀取時解壓成本也更高。
In Memory區資料的訪問
當訪問In Memory區中的物件時,執行計劃中會出現新的INMEMORY關鍵字:
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 6 | 312 | 1 (0)| 00:00:01 |
| 1 | TABLE ACCESS INMEMORY FULL| TEST_IM | 6 | 312 | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
但這裡要注意的是, 當出現INMEMORY關鍵字時並不表示資料一定是在IM區獲得的. 這裡的INMEMORY只能說明TEST_IM表的INMEMORY屬性已被enable,對該表資料的訪問有可能是從IM區得到的.這裡使用前面的例子來說明這一點:
create table test_im(v varchar2(100)) inmemory pctused 1 pctfree 99 tablespace users;
insert into test_im select rpad('a',100,'a') from dual connect by level <=5;
commit;
SQL> select bytes/1024 from dba_segments where segment_name='TEST_IM';
BYTES/1024
----------
64
SQL> select * from TEST_IM;
……
SQL> select * from v$im_segments where segment_name='TEST_IM';
no rows selected
SQL> set autotrace traceonly
SQL> select * from test_im;
Elapsed: 00:00:00.03
Execution Plan
----------------------------------------------------------
Plan hash value: 2761107969
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5 | 260 | 1 (0)| 00:00:01 |
| 1 | TABLE ACCESS INMEMORY FULL| TEST_IM | 5 | 260 | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Note
-----
- dynamic statistics used: dynamic sampling (level=2)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
7 consistent gets
0 physical reads
0 redo size
800 bytes sent via SQL*Net to client
550 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
5 rows processed
這裡可以看到,TEST_IM表並不在IM區,但執行計劃顯示得是TABLE ACCESS INMEMORY FULL,說明執行計劃並不能作為判斷是否是從IM區獲取資料的依據.
隨著IM功能的引入,Oracle增加了一些新的統計資訊用於IM相關的統計,這裡可以使用IM scan rows來統計IM訪問的情況,繼續上面的例子:
SQL> select name,value from v$mystat, v$statname where v$mystat.statistic# = v$statname.statistic# and v$statname.name = 'IM scan rows';
NAME VALUE
---------------------------------------------------------------- ----------
IM scan rows 6
SQL> select * from test_im;
V
----------------------------------------------------------------------------------------------------
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
SQL> select name,value from v$mystat, v$statname where v$mystat.statistic# = v$statname.statistic# and v$statname.name = 'IM scan rows';
NAME VALUE
---------------------------------------------------------------- ----------
IM scan rows 6
IM scan rows統計值前後沒有變化,可見這裡的確沒有IM訪問.
SQL> insert into test_im select rpad('a',100,'a') from dual;
1 row created.
SQL> commit;
Commit complete.
SQL> select * from TEST_IM;
……
SQL> select SEGMENT_NAME,INMEMORY_SIZE,BYTES,POPULATE_STATUS from v$im_segments where segment_name='TEST_IM';
SEGMENT_NAME INMEMORY_SIZE BYTES POPULATE_STATUS
-------------------- ------------- ---------- --------------------
TEST_IM 1179648 131072 COMPLETED
SQL> set autotrace traceonly
SQL> select * from test_im;
6 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 2761107969
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 6 | 312 | 1 (0)| 00:00:01 |
| 1 | TABLE ACCESS INMEMORY FULL| TEST_IM | 6 | 312 | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Note
-----
- dynamic statistics used: dynamic sampling (level=2)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
3 consistent gets
0 physical reads
0 redo size
805 bytes sent via SQL*Net to client
550 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
6 rows processed
SQL> select name,value from v$mystat, v$statname where v$mystat.statistic# = v$statname.statistic# and v$statname.name = 'IM scan rows';
NAME VALUE
---------------------------------------------------------------- ----------
IM scan rows 12
IM scan rows值增加了6, 說明這裡的資料是從IM區獲得的, 並且行數也完全吻合.
此外,觀察autotrace的結果可發現,在使用了IM訪問後,consistent gets也從之前的7降到了3。
IMCU(In Memory Compression Units)
IMCU類似於表空間中extent的概念,是列資料在IM區中記憶體分配塊的大小。後臺程式ora_w00*在裝載資料時,會分配自己的IMCU,並將分配給該程式的資料載入到該IMCU中。此後,當訪問IM區中的列資料時,我們在統計資訊中看到的consistent gets值也就是統計所訪問IMCU的個數和所需訪問metadata塊的個數之和。特定物件所分配IMCU的詳細資訊,可從檢視V_$IM_HEADER中查詢。而其metadata塊的資訊可從檢視V_$IM_SMU_CHUNK和V_$IM_SMU_HEAD查詢。
在In Memory內部,以IMCU為單位,Oracle維護了一個In Memory Storage Index,記錄IMCU單元中該列的最大值,最小值。此外,Oracle也會在metadata區為每個IMCU建立相應的metadata dictionary, metadata資訊中會有一些列的統計資訊。檢視V_$IM_COL_CU可以幫助查詢這些metadata dictionary資訊。
與IM相關的檢視:
SQL> SELECT VIEW_NAME FROM DBA_VIEWS WHERE VIEW_NAME LIKE 'V_$IM%';
VIEW_NAME
------------------------------------------------------------------------------------
V_$IM_SEGMENTS_DETAIL --記錄IM段物件的詳細儲存屬性
V_$IM_SEGMENTS --記錄IM段物件的儲存屬性
V_$IM_USER_SEGMENTS --記錄當前使用者下IM段物件的儲存屬性
V_$IM_TBS_EXT_MAP --記錄IM區1M子池物件的區間對映關係
V_$IM_SEG_EXT_MAP --記錄IM區物件的所有區間對映關係
V_$IM_HEADER --記錄IM區物件所分配IMCU的詳細資訊
V_$IM_COL_CU --記錄IMCU中基於列的統計資訊
V_$IM_SMU_HEAD
V_$IM_SMU_CHUNK
V_$IM_COLUMN_LEVEL --記錄IMCU中物件的列級壓縮屬性,若未在列級定義,則改檢視為空
10 rows selected.
--以上對各VIEW的註釋來自測試中的觀察,描述有可能欠準確。
與IM相關的等待事件:
SQL> select name from v$event_name where name like '%IM %';
NAME
----------------------------------------------------------------
IM buffer busy
enq: IM - contention for blr
IM CU busy
latch: IM area scb latch
latch: IM area sb latch
latch: IM seg hdr latch
latch: IM emb latch
enq: SY - IM populate by other session
IM populate completion
9 rows selected
與IM相關的統計資訊:
SQL> select name from v$statname where name like 'IM %' order by 1;
NAME
----------------------------------------------------------------
IM fetches by rowid from IMCU
IM fetches by rowid from disk
IM fetches by rowid from fetch list
IM fetches by rowid from journal
IM fetches by rowid row invalid in IMCU
IM populate (faststart) CUs accumulated write time (ms)
IM populate (faststart) CUs bytes read
……
198 rows selected.
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/21754115/viewspace-2085247/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 12c in memory option學習筆記二_資料訪問筆記
- vue學習筆記【基礎篇一】Vue筆記
- MySQL學習筆記【基礎篇】MySql筆記
- PHP學習筆記(1)–基礎知識篇PHP筆記
- python基礎學習筆記(一)Python筆記
- Oracle 12c In-Memory Option - 10Oracle
- Oracle 12c In-Memory Option - 9Oracle
- Oracle 12c In-Memory Option - 8Oracle
- Oracle 12c In-Memory Option - 7Oracle
- Oracle 12c In-Memory Option - 13Oracle
- Oracle 12c In-Memory Option - 6Oracle
- Oracle 12c In-Memory Option - 5Oracle
- Oracle 12c In-Memory Option - 4Oracle
- Oracle 12c In-Memory Option - 3Oracle
- Oracle 12c In-Memory Option - 2Oracle
- Oracle 12c In-Memory Option - 1Oracle
- CSS 基礎學習筆記CSS筆記
- node基礎學習筆記筆記
- Web基礎學習筆記Web筆記
- Redis基礎學習筆記Redis筆記
- Shell 學習筆記 基礎筆記
- Oracle基礎學習筆記Oracle筆記
- Java基礎學習筆記Java筆記
- [今日白記]Vue基礎的學習筆記(一)Vue筆記
- 深度學習word2vec筆記之基礎篇深度學習筆記
- 安卓初學基礎學習筆記安卓筆記
- Redux 基礎 - react 全家桶學習筆記(一)ReduxReact筆記
- Node基礎知識點--學習筆記(一)筆記
- DI、IOC基礎學習筆記筆記
- JavaScript學習筆記——基礎部分JavaScript筆記
- 彙編基礎學習筆記筆記
- 基礎知識學習筆記筆記
- Python基礎學習筆記Python筆記
- 影象拼接基礎學習筆記筆記
- 類的基礎學習筆記筆記
- Java基礎-學習筆記05Java筆記
- Java基礎-學習筆記06Java筆記
- Java基礎-學習筆記07Java筆記