In-Memory Column Store DML 처리
IM Column Store에서의 DML 처리를 살펴보겠습니다.
Data Loads – 시나리오 1
첫번째 시나리오는 SALES1 테이블을 디폴트 priority로 생성하고 non-direct path data load 수행했을 때입니다.
[oracle@New-Features-12c ~]$ sqlplus labuser/labuser@pdb1 SQL*Plus: Release 12.1.0.2.0 Production on Fri Aug 28 11:36:05 2015 Copyright (c) 1982, 2014, Oracle. All rights reserved. Last Successful login time: Fri Aug 28 2015 06:26:43 +00:00 Connected to: Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 – 64bit Production With the Partitioning, Oracle Label Security, OLAP, Advanced Analytics and Real Application Testing options SQL> create table sales1 as select * from sales where 1=2; Table created. SQL> alter table sales1 inmemory; Table altered. SQL> insert into sales1 select * from sales where rownum <= 10000; 10000 rows created. SQL> commit; Commit complete. |
Commit을 했음에도 불구하고 v$im_segments를 통해 확인했을 때 SALES1 테이블이 아직 population 되지 않았습니다.
SQL> col segment_name for a20 SQL> select segment_name, populate_status, bytes, inmemory_size, bytes_not_populated from v$im_segments where segment_name = ‘SALES1’; no rows selected |
IM transactions : Transactions issued by the session to In-Memory tables (i.e. the number of times COMMITs have been issued)
IM transactions rows journaled : Count of rows logged in the Transaction Journal by the session.
IM populate segments requested : The number of times the session has requested for In-Memory population of a segment.
세션 통계정보를 통해SALES1 테이블에 실행된 트랜젝션(IM transactions)은 1회이며 Transaction Journal에 기록된 로우 수(IM transactions rows journaled) 는 10000 이지만 해당 세그먼트에 대한 population 요청(IM populate segments requested)은 아직 없는 것을 알 수 있습니다.
SQL> set lines 120 SQL> col value for 999999999999999 SQL> select display_name, value from v$mystat m, v$statname n where m.statistic# = n.statistic# and n.display_name in ( ‘IM populate segments requested’ , ‘IM transactions’ , ‘IM transactions rows journaled’); DISPLAY_NAME VALUE —————————————————————- —————- IM transactions 1 IM transactions rows journaled 10000 IM populate segments requested 0 |
DBMS_INMEMORY.POPULATE 프로시저를 이용해서 수동으로 SALES1 테이블을 populate 합니다. 프로시저 실행 후 population 상태를 딕셔너리뷰에서 확인합니다.
SQL> execute dbms_inmemory.populate(‘LABUSER’,’SALES1′,null); PL/SQL procedure successfully completed. SQL> select segment_name, populate_status, bytes, inmemory_size, bytes_not_populated from v$im_segments where segment_name = ‘SALES1’; SEGMENT_NAME POPULATE_ BYTES INMEMORY_SIZE BYTES_NOT_POPULATED ——————– ——— ———- ————- ——————- SALES1 COMPLETED 458752 1179648 0 |
Population 상세 상태를 확인합니다. SALES1 테이블에 대해 7개 익스텐트가 생성되어 있고 여기에는 56개 블록이 할당되어 있으나 50개 블록이 사용중(DATABLOCKS)임을 알 수 있습니다. 사용 중인 50개 블록 모두 IM Column Store에 population 되어 있습니다 (BLOCKSINMEM)
SQL> col object_name for a20 SQL> select a.object_name, b.membytes, b.extents, b.blocks, b.datablocks, b.blocksinmem, b.bytes from v$im_segments_detail b, dba_objects a where a.data_object_id = b.dataobj and a.object_name = ‘SALES1’; OBJECT_NAME MEMBYTES EXTENTS BLOCKS DATABLOCKS BLOCKSINMEM BYTES ——————– ———- ———- ———- ———- ———– ———- SALES1 1179648 7 56 50 50 458752 |
Data Loads – 시나리오 2
이번에는 Insert as Select 구문으로 SALES1 테이블에 추가 데이터를 입력해 보겠습니다.
“IM transactions” 이 commit으로 인해 기존 1에서 2로 증가하고, “IM transactions rows journaled” 값이 10000에서 10100으로 변경되는 것을 볼 수 있습니다.
SQL> insert into sales1 select * from sales where rownum <= 100; 100 rows created. SQL> commit; Commit complete. SQL> select display_name, value from v$mystat m, v$statname n where m.statistic# = n.statistic# and n.display_name in ( ‘IM populate segments requested’ , ‘IM transactions’ , ‘IM transactions rows journaled’); DISPLAY_NAME VALUE —————————————————————- —————- IM transactions 2 IM transactions rows journaled 10100 IM populate segments requested 1 |
세그먼트의 population 상태를 확인해 보면 소량의 데이터만을 추가로 입력했기 때문에(100건) 신규로 할당된 익스텐트나 블록은 없고, 이미 할당된 익스텐트 내에 데이터가 추가된 케이스라고 할 수 있습니다 (기존 값과 비교) 이는 trickle repopulation 대상입니다
SQL> select a.object_name, b.membytes, b.extents, b.blocks, b.datablocks, b.blocksinmem, b.bytes from v$im_segments_detail b, dba_objects a where a.data_object_id = b.dataobj and a.object_name = ‘SALES1’; OBJECT_NAME MEMBYTES EXTENTS BLOCKS DATABLOCKS BLOCKSINMEM BYTES ——————– ———- ———- ———- ———- ———– ———- SALES1 1179648 7 56 50 50 458752 |
v$im_segments에서 BYTES_NOT_POPULATED 수치가 0으로 나타나는 이유는 BYTES_NOT_POPULATED 가 세그먼트에 추가되었으나 아직 population 되지 않은 신규 익스텐트의 사이즈만을 나타내기 때문입니다.
SQL> select segment_name, populate_status, bytes, inmemory_size, bytes_not_populated from v$im_segments where segment_name = ‘SALES1’; SEGMENT_NAME POPULATE_ BYTES INMEMORY_SIZE BYTES_NOT_POPULATED ——————– ——— ———- ————- ——————- SALES1 COMPLETED 458752 1179648 0 |
추가된 로우의 population 정보는 v$im_header 뷰에서 관련 정보를 확인합니다. 현재 다음 같은 상태임을 알 수 있습니다. 하나의 IMCU 만 생성되어 있으며 (v$im_header에는 IMCU 1개당 1개 로우 생성) 7개 디스크 익스텐트, 50개 블록에 저장된 10100개의 로우가 매핑되어 있음 IMCU에 매핑되어 있습니다.
Tricke repopulation이 발생했음 (REPOPULATED 1, TRICKLE_REPOPULATED 1)
SQL> select b.object_name, a.prepopulated, a.repopulated, a.trickle_repopulated, a.num_disk_extents, a.num_blocks, a.num_rows, a.num_cols from v$im_header a, dba_objects b where a.objd = b.data_object_id and b.object_name = ‘SALES1’; OBJECT_NAME PREPOPULATED REPOPULATED TRICKLE_REPOPULATED NUM_DISK_EXTENTS NUM_BLOCKS NUM_ROWS NUM_COLS ——————– ———— ———– ——————- —————- ———- ———- ———- SALES1 0 1 1 7 50 10100 7 |
Data Loads – 시나리오 3
이번에는 append 힌트를 사용하여 direct path insert를 해 보겠습니다. Repopulation이 필요한 새로운 extents 할당이 이루어진 것을 알 수 있습니다. 49 블록 (99-50) 이 IM Column Store에 아직 popuation 안되어 있습니다.
SQL> insert /*+ append */ into sales1 select * from sales where rownum <= 10000; 10000 rows created. SQL> commit; Commit complete. SQL> select a.object_name, b.membytes, b.extents, b.blocks, b.datablocks, b.blocksinmem, b.bytes from v$im_segments_detail b, dba_objects a where a.data_object_id = b.dataobj and a.object_name = ‘SALES1’; OBJECT_NAME MEMBYTES EXTENTS BLOCKS DATABLOCKS BLOCKSINMEM BYTES ——————– ———- ———- ———- ———- ———– ———- SALES1 1179648 14 112 99 50 917504 |
v$im_segments의 BYTES_NOT_POPULATED 값은 SALES1 테이블이 완전히 population 되지 않았음을 보여주고 있습니다.
SQL> select segment_name, populate_status, bytes, inmemory_size, bytes_not_populated from v$im_segments where segment_name = ‘SALES1’; 2 SEGMENT_NAME POPULATE_ BYTES INMEMORY_SIZE BYTES_NOT_POPULATED ——————– ——— ———- ————- ——————- SALES1 COMPLETED 917504 1179648 401408 |
수동으로 population을 합니다
force 옵션을 false로 하고 repopulate 프로시저를 수행한 후 population 상태를 확인해 보면 population이 아직 수행되지 않았음을 알 수 있습니다. 이는 force=>false 옵션이 IMCU 내 변경된 데이터만 (신규 IMCU가 아니라) population 시키는 옵션이기 때문입니다.
SQL> execute dbms_inmemory.repopulate(‘LABUSER’, ‘SALES1’, null, force=>false); PL/SQL procedure successfully completed. SQL> select segment_name, populate_status, bytes, inmemory_size, bytes_not_populated from v$im_segments where segment_name = ‘SALES1’; SEGMENT_NAME POPULATE_ BYTES INMEMORY_SIZE BYTES_NOT_POPULATED ——————– ——— ———- ————- ——————- SALES1 COMPLETED 917504 1179648 401408 |
false옵션을 true로 해서 수동으로 population 시킵니다. False=>true인 dbms_inmemory.repopulate 프로시저는 populate 프로시저와 동일하게 동작합니다. (population 되지 않은 디스크 익스텐트를 강제로 population 시킴)
SQL> execute dbms_inmemory.repopulate(‘LABUSER’, ‘SALES1’, null, force=>true); PL/SQL procedure successfully completed. SQL> select segment_name, populate_status, bytes, inmemory_size, bytes_not_populated from v$im_segments where segment_name = ‘SALES1’; SEGMENT_NAME POPULATE_ BYTES INMEMORY_SIZE BYTES_NOT_POPULATED ——————– ——— ———- ————- ——————- SALES1 COMPLETED 917504 1179648 0 |
Data Loads – 시나리오 4
이번에는 priority 속성을 high로 변경 후 direct path load 를 수행해 보겠습니다. 먼저 테이블 priority 변경 후, BYTES_NOT_POPULATED 이 0으로 population 완료 된 것을 확인합니다.
SQL> alter table sales1 inmemory priority high; Table altered. SQL> select segment_name, populate_status, bytes, inmemory_size, bytes_not_populated from v$im_segments where segment_name =’SALES1′; SEGMENT_NAME POPULATE_ BYTES INMEMORY_SIZE BYTES_NOT_POPULATED ——————– ——— ———- ————- ——————- SALES1 COMPLETED 917504 1179648 0 |
Direct path load로 데이터 입력 후 v$im_segments를 조회해 보면, 어느 정도 시간이 지난 후 (수초 ~ 1분) dbms_inmemory.repopulate 프로시저 실행이나 SALES1 테이블 조회와 같은 별도의 조치 없이도 population이 이루어 진 것을 확인할 수 있습니다.
SQL> insert /*+ append */ into sales1 select * from sales where rownum <= 10000; 10000 rows created. SQL> commit; Commit complete. SQL> select segment_name, populate_status, bytes, inmemory_size, bytes_not_populated from v$im_segments where segment_name = ‘SALES1’; SEGMENT_NAME POPULATE_ BYTES INMEMORY_SIZE BYTES_NOT_POPULATED ——————– ——— ———- ————- ——————- SALES1 COMPLETED 2097152 1179648 401408 SQL> select segment_name, populate_status, bytes, inmemory_size, bytes_not_populated from v$im_segments where segment_name = ‘SALES1’; SEGMENT_NAME POPULATE_ BYTES INMEMORY_SIZE BYTES_NOT_POPULATED ——————– ——— ———- ————- ——————- SALES1 COMPLETED 2097152 1179648 0 |
Very soon this web site will be famous amid all blogging visitors, due to it’s good articles or reviews