16
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Oracle AI Database In-Memory でクエリを1000倍高速化してみてみた

16
Last updated at Posted at 2026-03-24

今回は、Oracle AI Database In-Memory を実際に有効化し、どのくらいデータが圧縮されるのか、クエリ性能がどのくらい向上するのかを、実測値ベースで確認してみます。
特に、Disk 読み取り時と In-Memory 読み取り時で、実行時間と物理 I/O がどの程度変わるのかを比較しながら見てみてみます。
in_memoryイメージ.png

Oracle AI Database In-Memory は、Oracle AI Databaseにカラム機能を追加し、分析クエリを透過的に桁違いに高速化します。Oracle AI Database In-Memoryは、リアルタイム・データに基づく意思決定を可能にし、コストの削減、生産性の向上、競争力の強化を実現します。

  • IM列ストア
    表、パーティションおよび個別の列のコピーが、高速スキャン向けに最適化された圧縮列形式で保持されます。各表またはビューのデータが行ではなく列ごとに格納されます。各列は、個別の行サブセットに分割されます。インメモリー圧縮単位(IMCU)というコンテナに、表セグメント内の行のサブセットのすべての列が格納されます。
  • SGAの記憶域
    IM列ストアは、システム・グローバル領域(SGA)のオプション部分である、インメモリー領域に存在します。IM列ストアは行ベース・ストレージまたはデータベース・バッファ・キャッシュに代わるものではありませんが、それを補完します。データベースでは、データは、行ベースおよび列形式の両方でメモリー内に存在できるようになり、両方の長所が提供されます。IM列ストアにより、ディスク形式とは無関係な、トランザクションの一貫性がある、表データのコピーがさらに提供されます。
    IM01.png

Oracle AI Database In-Memory には、次のような特徴があります。

  • デュアル形式アーキテクチャ
    従来の行形式と新しいインメモリ列形式を同時に使用してテーブルを表現します。これにより、同じデータベース内の同じデータに対してトランザクション・データ処理と分析データ処理を実行できます。

  • スケールアウト
    Oracle Real Application Clusters(RAC)全体にわたり、透過的なインメモリのスケールアウトを可能にします。単一ノードのメモリに制限されることなく、クラスタ内のあらゆるノードにわたり透過的にメモリにアクセスできるため、単一ノードよりも大きな列ストアを作成する機能を提供します。

  • 高可用性
    アクティブ・データ・ガード構成では、スタンバイ・データベース上にインメモリ列ストアを作成、入力、維持することができます。これにより、分析ワークロードのためにスタンバイ・データベースのCPUおよびメモリ・リソースをフルに活用できるとともに、プライマリ・データベースとその関連スタンバイ・データベース全体にわたり、インメモリ列ストアをフレキシブルに配置することができます。

  • インメモリ・フォルト・トレランス
    Oracle Exadataクラスタのノード全体にわたりインメモリ・データを分散および複製するため、ノードの障害による速度低下を排除します。ノードに障害が発生した場合、クエリは生き残ったノード上のデータの複製を透過的に使用できます。

  • 互換性
    Oracle AI Database互換のアプリケーションにOracle AI Database In-Memoryを導入する場合、アプリケーションの変更は必要ありません。オラクルの広範な機能、データ型、APIはすべて透過的に機能し続けます。

  • 自動インメモリ
    インメモリ列ストアの内容を使用状況に応じて自動的に管理し、手作業を必要とせずにデータベース・メモリを最大限に活用します。

  • 複数のデータ・ソースにわたるリアルタイムのレポート
    外部データ・ソースの直接投入を可能にし、ユーザーがOracle AI Databaseの内部および外部のすべてのデータ・ソースに対して分析クエリを実行できるようにします。

  • Exadata Flash Cacheにおけるデータベース・インメモリ・フォーマット
    Exadata Flash Cacheにおいてインメモリ・カラム型フォーマットをサポートします。
    これにより、Exadataのお客様は、テラバイト規模の容量を持つExadata Flash Cacheにインメモリ・カラム型ストアを拡張し、これまで以上に大規模なデータフットプリントに対して分析クエリを実行できるようになります。
    IM03.png

ということで、Oracle AI Database In-Memory の有無でどのくらいデータが圧縮され、クエリ速度が向上するか確認してみてみます。

■ 環境

今回は、Oracle Cloud の Oracle AI Database 26ai を使用し、次を参考に作成します。
ライセンスは、In-Memoryオプションある EE Extreme Performance を使用します。

■ In-Memoryパラメータ設定

1) In-Memory有効化

ALTER SYSTEM SET inmemory_size = 16G SCOPE=SPFILE;

SHUTDOWN IMMEDIATE;
STARTUP;

2) In-Memory有効化確認

SQL> SHOW PARAMETER inmemory
	NAME                                        TYPE        VALUE
	------------------------------------------- ----------- -------
	inmemory_adg_enabled       boolean TRUE
	inmemory_automatic_level   string   OFF
	inmemory_clause_default    string
	inmemory_deep_vectorization boolean TRUE
	inmemory_expressions_usage string   ENABLE
	inmemory_force                   string   DEFAULT
	inmemory_graph_algorithm_execution string   DEFAULT
	inmemory_max_populate_servers integer 32
	inmemory_optimized_arithmetic string   DISABLE
	inmemory_optimized_date    string   DISABLE
	inmemory_prefer_xmem_memcompress string
	inmemory_prefer_xmem_priority string
	inmemory_query                  string   ENABLE
	inmemory_size                     big integer 16G
	inmemory_trickle_repopulate_servers_percent integer 1
	inmemory_virtual_columns   string   MANUAL
	inmemory_xmem_size           big integer 0
	optimizer_inmemory_aware  boolean TRUE


SQL> SELECT pool, alloc_bytes, used_bytes, populate_status
   FROM   v$inmemory_area
   ORDER  BY pool;

	POOL             ALLOC_BYTES  USED_BYTES POPULATE_STATUS
	________________ ____________ __________ _______________
	1MB POOL         117440512000          0 DONE
	1MB POOL         113760010240          0 DONE
	1MB POOL         117440512000          0 DONE
	64KB POOL         48766451712          0 DONE
	64KB POOL         50314870784          0 DONE
	64KB POOL         50314870784          0 DONE

■ スキーマ作成

1) 表領域作成

create bigfile tablespace imdemo
  datafile 'IMDEMO.dbf' size 150g
  autoextend on next 10g maxsize 1t
  extent management local segment space management auto;

2) ユーザー作成

create user imdemo identified by "********"
  default tablespace imdemo
  temporary tablespace temp
  quota unlimited on imdemo;

grant create session, create table, create procedure, create sequence to imdemo;
grant execute on sys.dbms_inmemory to imdemo; 
-- 必要に応じて: grant create view, create materialized view, etc.

■ データ作成

今回は、分析クエリ向けの検証用として、ディメンション表とファクト表を作成します。

  • ディメンション表は、カテゴリ・顧客・地域といった集計軸を持つ小規模な参照表
  • ファクト表は、大量データを格納する売上明細表

という構成です。

ファクト表 FACT_SALES は月次レンジ・パーティションとし、直近 2 か月分のみを INMEMORY、それ以前を NO INMEMORY に設定します。これにより、メモリ使用量を抑えつつ、In-Memory の効果をわかりやすく確認できるようにします。

● テーブル一覧

・ディメンション表(小さい参照表、JOIN用)

DIM_PRODUCT(商品マスタ)
	prod_id:商品ID(結合キー)
	category:カテゴリ(集計軸)
	用途:FACT_SALES.prod_id とJOINし、カテゴリ別集計を行う。

DIM_CUSTOMER(顧客マスタ)
    cust_id:顧客ID(結合キー)
    segment:顧客セグメント(集計軸)
    signup_dt:登録日(任意)
	用途:顧客軸の分析を増やしたい場合にJOINする(今回の基本SQLは region/product join)

DIM_REGION(地域マスタ)
	region_id:地域ID(結合キー)
	region_name:地域名
	用途:FACT_SALES.region_id とJOINし、地域別集計を行う。 

・ファクト表(大量データ、パーティション+In-Memoryの主役)

FACT_SALES(売上明細):月次レンジ・パーティション(例:P01〜P06)
    sale_dt:日付(パーティションキー)
	cust_id/prod_id/region_id:ディメンション結合キー
	amount:売上(集計対象)
	pad:行サイズを膨らませて「Diskは巨大、IMは圧縮」を作りやすくする列   

1) imdemoユーザーログイン
conn imdemo/Password

2) パラメータ定義(サイズ調整用)設定

SQL
-- (IMDEMO)
-- ===== 調整パラメータ =====
define P_MONTHS         = 6          -- パーティション月数(例: 6)
define P_ROWS_PER_MONTH = 5000000    -- 1パーティションあたり行数(例: 500万)
define P_PAD_LEN        = 4000        -- 行サイズを膨らませるパディング長(例: 4000
define P_DEGREE         = 8          -- PARALLEL度(環境に合わせて)
define P_START_DATE     = '2025-01-01'  -- 開始日(YYYY-MM-DD)


set serveroutput on
set timing on
alter session set nls_date_format = 'YYYY-MM-DD';
alter session set optimizer_dynamic_sampling = 0;
alter session set parallel_degree_policy = manual;

3) DDL: ディメンション+ファクト(レンジ月次パーティション)
fact_sales を月次パーティション
直近2か月分のみを INMEMORY とし、それ以前は NO INMEMORY とすることで、メモリ使用量を抑えつつ In-Memory の効果を確認します。
JOIN を含む集計クエリでも、結果セット自体は数十行に収まるようにしています。

SQL
-- クリーンアップ(再実行用)
begin
  execute immediate 'drop table fact_sales purge';
exception when others then null;
end;
/
begin execute immediate 'drop table dim_product purge'; exception when others then null; end;
/
begin execute immediate 'drop table dim_customer purge'; exception when others then null; end;
/
begin execute immediate 'drop table dim_region purge'; exception when others then null; end;
/
begin execute immediate 'drop sequence seq_sale_id'; exception when others then null; end;
/

create sequence seq_sale_id cache 100000;

-- ディメンション
create table dim_region (
  region_id number primary key,
  region_name varchar2(30)
);

create table dim_product (
  prod_id number primary key,
  category varchar2(30),
  brand varchar2(30)
);

create table dim_customer (
  cust_id number primary key,
  segment varchar2(20),
  signup_dt date
);

-- ファクト(月次パーティション:明示的に6パーティション作成)
-- 直近2パーティションのみ INMEMORY(後でALTERで制御)
create table fact_sales (
  sale_id    number not null,
  sale_dt    date   not null,
  cust_id    number not null,
  prod_id    number not null,
  region_id  number not null,
  qty        number,
  amount     number(12,2),
  channel    varchar2(10),
  pad        varchar2(4000)
)
partition by range (sale_dt)
(
  partition p01 values less than (date '2025-02-01'),
  partition p02 values less than (date '2025-03-01'),
  partition p03 values less than (date '2025-04-01'),
  partition p04 values less than (date '2025-05-01'),
  partition p05 values less than (date '2025-06-01'),
  partition p06 values less than (date '2025-07-01')
)
nologging
parallel &P_DEGREE
-- テーブル定義としてINMEMORYを付けてもよいですが、
-- 今回はパーティション単位で ON/OFF するのでテーブル自体は付けない(後でALTER)。
;

-- 参照・結合を安定させるために最低限の索引(ロウストア側)
drop index ix_fact_sales_dt;
drop index ix_fact_sales_prod;
drop index ix_fact_sales_cust;
drop index ix_fact_sales_region;

create index ix_fact_sales_dt on fact_sales(sale_dt) local nologging parallel &P_DEGREE;
create index ix_fact_sales_prod on fact_sales(prod_id) local nologging parallel &P_DEGREE;
create index ix_fact_sales_cust on fact_sales(cust_id) local nologging parallel &P_DEGREE;
create index ix_fact_sales_region on fact_sales(region_id) local nologging parallel &P_DEGREE;

■ データ生成(パラメータでサイズ調整)

PAD_LEN=4000, 500万行/月 x2パーティション で作成して In-Memory=OFF の SQL Elapsed が十分に時間かかるか確認し、必要に応じて サイズを調整します。

1) ディメンション投入

-- 地域100
insert /*+ append */ into dim_region
select level as region_id,
       'REGION_'||to_char(level,'fm000') as region_name
from dual connect by level <= 100;

-- 製品5000(カテゴリ/ブランドに偏りを持たせ圧縮・集計が効きやすい)
insert /*+ append */ into dim_product
select level as prod_id,
       'CAT_'||to_char(mod(level,50)+1,'fm00') as category,
       'BRAND_'||to_char(mod(level,200)+1,'fm000') as brand
from dual connect by level <= 5000;

-- 顧客100000
insert /*+ append */ into dim_customer
select level as cust_id,
       case mod(level,4)
         when 0 then 'ENTERPRISE'
         when 1 then 'SMB'
         when 2 then 'CONSUMER'
         else 'PUBLIC'
       end as segment,
       date'2020-01-01' + mod(level, 365*4) as signup_dt
from dual connect by level <= 100000;

commit;

2) パーティション P05/P06 に各500万行ロード

declare
  v_rows     number := &P_ROWS_PER_MONTH;  -- 500万
  v_pad      number := &P_PAD_LEN;         -- 4000
  v_start_dt date   := date '2025-01-01';
  v_sql      clob;
begin
  v_sql := q'[
    insert /*+ append parallel(fact_sales, &P_DEGREE) */ into fact_sales
    select
      seq_sale_id.nextval as sale_id,
      add_months(:p_start_dt, :p_m) + mod(level-1, 28) as sale_dt,
      mod(level, 100000) + 1 as cust_id,
      mod(level, 5000)   + 1 as prod_id,
      mod(level, 100)    + 1 as region_id,
      mod(level, 10)     + 1 as qty,
      round(mod(level,1000) + dbms_random.value, 2) as amount,
      case mod(level,3) when 0 then 'WEB' when 1 then 'STORE' else 'DIRECT' end as channel,
      rpad('x', :p_pad, 'x') as pad
    from dual
    connect by level <= :p_rows
  ]';

  -- 0起点: 4=2025-05, 5=2025-06
  for m in 4 .. 5 loop
    execute immediate v_sql using v_start_dt, m, v_pad, v_rows;
    commit;
  end loop;
end;
/

3) 統計情報取得(重要)

exec dbms_stats.gather_table_stats(user,'DIM_REGION', cascade=>true);
exec dbms_stats.gather_table_stats(user,'DIM_PRODUCT', cascade=>true);
exec dbms_stats.gather_table_stats(user,'DIM_CUSTOMER', cascade=>true);
exec dbms_stats.gather_table_stats(user,'FACT_SALES', cascade=>true);

3) データロード確認
fact_sales表の partition(p05) と partition(p06)のデータ量を確認

SQL> select count(*) from fact_sales partition(p05);

COUNT(*)
________
 5000000

SQL> select count(*) from fact_sales partition(p06);

COUNT(*)
________
 5000000

■ In-Memory 設定

(直近2パーティションだけON)+ Populate

1) (直近2パーティションだけON)+ Populate
直近2か月(例:p05,p06)だけ IM に載せ、他はNOにします。圧縮方式はまず QUERY HIGH で実施

-- 古い分はIMに載せない(IM 48Gに収めるため)
alter table fact_sales modify partition p01 no inmemory;
alter table fact_sales modify partition p02 no inmemory;
alter table fact_sales modify partition p03 no inmemory;
alter table fact_sales modify partition p04 no inmemory;

-- 直近2パーティションのみINMEMORY(デモで効かせる部分)
alter table fact_sales modify partition p05 inmemory memcompress for query high;
alter table fact_sales modify partition p06 inmemory memcompress for query high;

-- ディメンションも小さいのでIM化(JOIN時の効きやすさを上げる)
alter table dim_product  inmemory memcompress for query low;
alter table dim_customer inmemory memcompress for query low;
alter table dim_region   inmemory memcompress for query low;

2) Populate(明示的に載せる)

begin
  sys.dbms_inmemory.populate(user,'DIM_PRODUCT');
  sys.dbms_inmemory.populate(user,'DIM_CUSTOMER');
  sys.dbms_inmemory.populate(user,'DIM_REGION');
  sys.dbms_inmemory.populate(user,'FACT_SALES');
end;
/

■ 圧縮率(Disk vs IM)確認

1) IM領域使用状況

SQL
select * from v$inmemory_area;
SQL実行結果
POOL             ALLOC_BYTES  USED_BYTES POPULATE_STATUS CON_ID
________________ ____________ __________ _______________ ______
1MB POOL         117440512000  795869184 DONE                 3
64KB POOL         50314870784  149422080 DONE                 3
IM POOL METADATA     16777216   16777216 DONE                 3

2) セグメント/パーティションごとのディスクサイズとIMサイズ

SQL
column segment_name format a20
column partition_name format a10
select
  owner, segment_name, partition_name,
  round(bytes/1024/1024/1024, 2) as disk_gb,
  round(inmemory_size/1024/1024/1024, 2) as im_gb,
  case when inmemory_size > 0 then round(bytes / inmemory_size, 2) end as disk_to_im_ratio
from v$im_segments
where owner = user
order by segment_name, partition_name;
SQL実行結果
OWNER  SEGMENT_NAME PARTITION_NAME DISK_GB IM_GB DISK_TO_IM_RATIO
______ ____________ ______________ _______ _____ ________________
IMDEMO DIM_CUSTOMER                      0     0             0.87
IMDEMO DIM_PRODUCT                       0     0             0.14
IMDEMO DIM_REGION                        0     0             0.04
IMDEMO FACT_SALES   P05              38.15  0.44            87.23
IMDEMO FACT_SALES   P06              38.15  0.44            87.23

3) どのパーティションが In-Memory か確認(メタデータ)

SQL
column partition_name format a10
column inmemory format a10
select partition_name, inmemory, inmemory_compression
from user_tab_partitions
where table_name = 'FACT_SALES'
order by partition_position;
SQL実行結果
PARTITION_NAME INMEMORY INMEMORY_COMPRESSION
______________ ________ ____________________
P01            DISABLED
P02            DISABLED
P03            DISABLED
P04            DISABLED
P05            ENABLED  FOR QUERY HIGH
P06            ENABLED  FOR QUERY HIGH

6 rows selected.

■ デモ

● Step 1. P05/P06がIMに載っている(圧縮されている)ことを確認

1) In-Memory化した Diskサイズ と In-Memoryサイズを確認

SQL
column segment_name format a20
column partition_name format a10

select
  owner, segment_name, partition_name,
  round(bytes/1024/1024/1024, 2)          as disk_gb,
  round(inmemory_size/1024/1024/1024, 2)  as im_gb,
  round(bytes/nullif(inmemory_size,0), 2) as disk_to_im_ratio
from v$im_segments
where owner = 'IMDEMO'
  and segment_name = 'FACT_SALES'
  and partition_name in ('P05','P06')
order by partition_name;
実行結果
OWNER  SEGMENT_NAME PARTITION_NAME DISK_GB IM_GB DISK_TO_IM_RATIO
______ ____________ ______________ _______ _____ ________________
IMDEMO FACT_SALES   P05              38.15  0.44            87.23
IMDEMO FACT_SALES   P06              38.15  0.44            87.23
SQL
select * from v$inmemory_area;
実行結果
POOL             ALLOC_BYTES  USED_BYTES POPULATE_STATUS CON_ID
________________ ____________ __________ _______________ ______
1MB POOL         117440512000  795869184 DONE                 3
64KB POOL         50314870784  149422080 DONE                 3
IM POOL METADATA     16777216   16777216 DONE                 3

● Step 2. 計測の共通設定

SQL
set timing on
set lines 200 pages 200
alter session set statistics_level = all;
alter session set result_cache_mode = manual;

● Step 3. IM OFF(ディスク読み)を “コールド” で測定

1) SYSで buffer cache flush

SQL
conn / as sysdba
alter system flush buffer_cache;

2) imdemoユーザーで In-Memory=OFF で SQL実行
統計差分のスナップショット→実行→差分

SQL
conn imdemo/password

alter session set inmemory_query = disable;

var prb_before number
var slr_before number
begin
  select
    max(case when n.name = 'physical read bytes'   then s.value end),
    max(case when n.name = 'session logical reads' then s.value end)
  into :prb_before, :slr_before
  from v$sesstat s join v$statname n on n.statistic# = s.statistic#
  where s.sid = sys_context('USERENV','SID')
    and n.name in ('physical read bytes','session logical reads');
end;
/

-- デモSQL(結果は30行)
select /*+ gather_plan_statistics
           parallel(f 8) full(f)
           parallel(p 8) full(p)
           parallel(r 8) full(r)
           no_result_cache
        */
       r.region_name,
       p.category,
       sum(f.amount) as sum_amount
from fact_sales f
join dim_region  r on r.region_id = f.region_id
join dim_product p on p.prod_id   = f.prod_id
where f.sale_dt >= date'2025-05-01'
  and f.sale_dt <  date'2025-07-01'
group by r.region_name, p.category
order by sum_amount desc
fetch first 30 rows only;

select * from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST +IOSTATS'));

var prb_after number
var slr_after number
begin
  select
    max(case when n.name = 'physical read bytes'   then s.value end),
    max(case when n.name = 'session logical reads' then s.value end)
  into :prb_after, :slr_after
  from v$sesstat s join v$statname n on n.statistic# = s.statistic#
  where s.sid = sys_context('USERENV','SID')
    and n.name in ('physical read bytes','session logical reads');
end;
/

select
  (:prb_after - :prb_before) as delta_physical_read_bytes,
  (:slr_after - :slr_before) as delta_session_logical_reads
from dual;
実行結果
SQL> alter session set inmemory_query = disable;

Session altered.

Elapsed: 00:00:00.002
SQL>
SQL> var prb_before number
SQL> var slr_before number
SQL> begin
  2    select
  3      max(case when n.name = 'physical read bytes'   then s.value end),
  4      max(case when n.name = 'session logical reads' then s.value end)
  5    into :prb_before, :slr_before
  6    from v$sesstat s join v$statname n on n.statistic# = s.statistic#
  7    where s.sid = sys_context('USERENV','SID')
  8      and n.name in ('physical read bytes','session logical reads');
  9  end;
 10* /

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.025
SQL>
SQL> -- デモSQL(結果は30行)
SQL> select /*+ gather_plan_statistics
  2             parallel(f 8) full(f)
  3             parallel(p 8) full(p)
  4             parallel(r 8) full(r)
  5             no_result_cache
  6          */
  7         r.region_name,
  8         p.category,
  9         sum(f.amount) as sum_amount
 10  from fact_sales f
 11  join dim_region  r on r.region_id = f.region_id
 12  join dim_product p on p.prod_id   = f.prod_id
 13  where f.sale_dt >= date'2025-05-01'
 14    and f.sale_dt <  date'2025-07-01'
 15  group by r.region_name, p.category
 16  order by sum_amount desc
 17* fetch first 30 rows only;

REGION_NAME CATEGORY SUM_AMOUNT
___________ ________ ___________
REGION_100  CAT_01   54950021.57
REGION_099  CAT_50   54850089.18
REGION_098  CAT_49   54749867.81
REGION_097  CAT_48   54650005.96
REGION_096  CAT_47   54550089.65
REGION_095  CAT_46   54450035.33
REGION_094  CAT_45   54349934.09
REGION_093  CAT_44   54249968.86
REGION_092  CAT_43   54150124.27
REGION_091  CAT_42   54050007.81
REGION_090  CAT_41   53949878.89
REGION_089  CAT_40    53849952.7
REGION_088  CAT_39    53749973.5
REGION_087  CAT_38   53650081.76
REGION_086  CAT_37   53549950.97
REGION_085  CAT_36   53449992.04
REGION_084  CAT_35   53350022.29
REGION_083  CAT_34   53249868.64
REGION_082  CAT_33   53150025.78
REGION_081  CAT_32    53050125.4
REGION_080  CAT_31   52950155.09
REGION_079  CAT_30   52849982.15
REGION_078  CAT_29   52750038.22
REGION_077  CAT_28   52650104.43
REGION_076  CAT_27   52549911.77
REGION_075  CAT_26   52450047.17
REGION_074  CAT_25   52349919.56
REGION_073  CAT_24   52250070.28
REGION_072  CAT_23   52150014.54
REGION_071  CAT_22    52049971.3

30 rows selected.

Elapsed: 00:02:41.706
SQL>
SQL> select * from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST +IOSTATS'));

PLAN_TABLE_OUTPUT
_____________________________________________________________________________________________________________________________________________________________________
SQL_ID  cdmv00926pnnx, child number 7
-------------------------------------
select /*+ gather_plan_statistics            parallel(f 8) full(f)
      parallel(p 8) full(p)            parallel(r 8) full(r)
no_result_cache         */        r.region_name,        p.category,
   sum(f.amount) as sum_amount from fact_sales f join dim_region  r on
r.region_id = f.region_id join dim_product p on p.prod_id   = f.prod_id
where f.sale_dt >= date'2025-05-01'   and f.sale_dt <  date'2025-07-01'
group by r.region_name, p.category order by sum_amount desc fetch first
30 rows only

Plan hash value: 403177439

---------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                 | Name                      | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Reads  |  OMem |  1Mem | Used-Mem |
---------------------------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                          |                           |      1 |        |     30 |00:02:41.66 |      31 |      4 |       |       |          |
|*  1 |  COUNT STOPKEY                            |                           |      1 |        |     30 |00:02:41.66 |      31 |      4 |       |       |          |
|   2 |   TEMP TABLE TRANSFORMATION               |                           |      1 |        |     30 |00:02:41.66 |      31 |      4 |       |       |          |
|   3 |    LOAD AS SELECT (CURSOR DURATION MEMORY)| SYS_TEMP_0FD9D662C_8C9E4E |      1 |        |      0 |00:00:00.02 |       7 |      2 |  1024 |  1024 |          |
|   4 |     PX COORDINATOR                        |                           |      1 |        |    100 |00:00:00.01 |       5 |      0 | 73728 | 73728 |          |
|   5 |      PX SEND QC (RANDOM)                  | :TQ10001                  |      0 |    100 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|   6 |       HASH GROUP BY                       |                           |      0 |    100 |      0 |00:00:00.01 |       0 |      0 |  1215K|  1215K|          |
|   7 |        PX RECEIVE                         |                           |      0 |    100 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|   8 |         PX SEND HASH                      | :TQ10000                  |      0 |    100 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|   9 |          KEY VECTOR CREATE BUFFERED       | :KV0000                   |      0 |    100 |      0 |00:00:00.01 |       0 |      0 |  9216 |  9216 |          |
|  10 |           PX BLOCK ITERATOR               |                           |      0 |    100 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|* 11 |            TABLE ACCESS FULL              | DIM_REGION                |      0 |    100 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|  12 |    LOAD AS SELECT (CURSOR DURATION MEMORY)| SYS_TEMP_0FD9D662D_8C9E4E |      1 |        |      0 |00:00:00.01 |       5 |      0 |  1024 |  1024 |          |
|  13 |     PX COORDINATOR                        |                           |      1 |        |     50 |00:00:00.01 |       5 |      0 | 73728 | 73728 |          |
|  14 |      PX SEND QC (RANDOM)                  | :TQ20001                  |      0 |     50 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|  15 |       HASH GROUP BY                       |                           |      0 |     50 |      0 |00:00:00.01 |       0 |      0 |  1264K|  1264K|          |
|  16 |        PX RECEIVE                         |                           |      0 |     50 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|  17 |         PX SEND HASH                      | :TQ20000                  |      0 |     50 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|  18 |          KEY VECTOR CREATE BUFFERED       | :KV0001                   |      0 |     50 |      0 |00:00:00.01 |       0 |      0 |  9216 |  9216 |          |
|  19 |           PX BLOCK ITERATOR               |                           |      0 |   5000 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|* 20 |            TABLE ACCESS FULL              | DIM_PRODUCT               |      0 |   5000 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|  21 |    PX COORDINATOR                         |                           |      1 |        |     30 |00:02:41.60 |      18 |      2 |  9216 |  9216 | 8192  (0)|
|  22 |     PX SEND QC (ORDER)                    | :TQ30002                  |      0 |   3536 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|  23 |      VIEW                                 |                           |      0 |   3536 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|* 24 |       SORT ORDER BY STOPKEY               |                           |      0 |   3536 |      0 |00:00:00.01 |       0 |      0 | 18432 | 18432 | 2048  (0)|
|  25 |        PX RECEIVE                         |                           |      0 |     30 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|  26 |         PX SEND RANGE                     | :TQ30001                  |      0 |     30 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|* 27 |          SORT ORDER BY STOPKEY            |                           |      0 |     30 |      0 |00:00:00.01 |       0 |      0 | 18432 | 18432 | 2048  (0)|
|* 28 |           HASH JOIN                       |                           |      0 |   3536 |      0 |00:00:00.01 |       0 |      0 |  1449K|  1449K| 1705K (0)|
|  29 |            TABLE ACCESS FULL              | SYS_TEMP_0FD9D662C_8C9E4E |      0 |    100 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|* 30 |            HASH JOIN                      |                           |      0 |   3536 |      0 |00:00:00.01 |       0 |      0 |  1573K|  1573K| 1715K (0)|
|  31 |             TABLE ACCESS FULL             | SYS_TEMP_0FD9D662D_8C9E4E |      0 |     50 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|  32 |             VIEW                          | VW_VT_E41ECF03            |      0 |   3536 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|  33 |              HASH GROUP BY                |                           |      0 |   3536 |      0 |00:00:00.01 |       0 |      0 |  1107K|  1107K| 1197K (0)|
|  34 |               PX RECEIVE                  |                           |      0 |   3536 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|  35 |                PX SEND HASH               | :TQ30000                  |      0 |   3536 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|  36 |                 VECTOR GROUP BY           |                           |      0 |   3536 |      0 |00:00:00.01 |       0 |      0 | 98304 | 98304 |  175K (0)|
|  37 |                  HASH GROUP BY            |                           |        |   3536 |        |            |         |        |  1647K|  1647K|          |
|  38 |                   KEY VECTOR USE          | :KV0000                   |      0 |   9972K|      0 |00:00:00.01 |       0 |      0 |   299M|  5750K|          |
|  39 |                    KEY VECTOR USE         | :KV0001                   |      0 |   9972K|      0 |00:00:00.01 |       0 |      0 |   256M|  5340K|          |
|  40 |                     PX BLOCK ITERATOR     |                           |      0 |     10M|      0 |00:00:00.01 |       0 |      0 |       |       |          |
|* 41 |                      TABLE ACCESS FULL    | FACT_SALES                |      0 |     10M|      0 |00:00:00.01 |       0 |      0 |       |       |          |
---------------------------------------------------------------------------------------------------------------------------------------------------------------------

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

   1 - filter(ROWNUM<=30)
  11 - access(:Z>=:Z AND :Z<=:Z)
  20 - access(:Z>=:Z AND :Z<=:Z)
  24 - filter(ROWNUM<=30)
  27 - filter(ROWNUM<=30)
  28 - access("ITEM_8"=INTERNAL_FUNCTION("C0"))
  30 - access("ITEM_9"=INTERNAL_FUNCTION("C0"))
  41 - access(:Z>=:Z AND :Z<=:Z)

Note
-----
   - dynamic statistics used: dynamic sampling (level=AUTO (SYSTEM))
   - Degree of Parallelism is 8 because of table property
   - vector transformation used for this statement


78 rows selected.

Elapsed: 00:00:00.051
SQL>
SQL> var prb_after number
SQL> var slr_after number
SQL> begin
  2    select
  3      max(case when n.name = 'physical read bytes'   then s.value end),
  4      max(case when n.name = 'session logical reads' then s.value end)
  5    into :prb_after, :slr_after
  6    from v$sesstat s join v$statname n on n.statistic# = s.statistic#
  7    where s.sid = sys_context('USERENV','SID')
  8      and n.name in ('physical read bytes','session logical reads');
  9  end;
 10* /

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.023
SQL>
SQL> select
  2    (:prb_after - :prb_before) as delta_physical_read_bytes,
  3    (:slr_after - :slr_before) as delta_session_logical_reads
  4* from dual;

DELTA_PHYSICAL_READ_BYTES DELTA_SESSION_LOGICAL_READS
_________________________ ___________________________
              81936908288                    10003886

Elapsed: 00:00:00.004
SQL>

● Step 4. IM ON(メモリ読み)をコールドで測定

1) SYSで buffer cache flush

conn / as sysdba
alter system flush buffer_cache;

2) imdemoユーザーで In-Memory=ON で SQL実行
統計差分のスナップショット→実行→差分

SQL
conn imdemo/...

alter session set inmemory_query = enable;

var prb_before number
var slr_before number
begin
  select
    max(case when n.name = 'physical read bytes'   then s.value end),
    max(case when n.name = 'session logical reads' then s.value end)
  into :prb_before, :slr_before
  from v$sesstat s join v$statname n on n.statistic# = s.statistic#
  where s.sid = sys_context('USERENV','SID')
    and n.name in ('physical read bytes','session logical reads');
end;
/

-- デモSQL(結果は30行)∂
select /*+ gather_plan_statistics
           parallel(f 8) full(f)
           parallel(p 8) full(p)
           parallel(r 8) full(r)
           no_result_cache
        */
       r.region_name,
       p.category,
       sum(f.amount) as sum_amount
from fact_sales f
join dim_region  r on r.region_id = f.region_id
join dim_product p on p.prod_id   = f.prod_id
where f.sale_dt >= date'2025-05-01'
  and f.sale_dt <  date'2025-07-01'
group by r.region_name, p.category
order by sum_amount desc
fetch first 30 rows only;

select * from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST +IOSTATS'));

var prb_after number
var slr_after number
begin
  select
    max(case when n.name = 'physical read bytes'   then s.value end),
    max(case when n.name = 'session logical reads' then s.value end)
  into :prb_after, :slr_after
  from v$sesstat s join v$statname n on n.statistic# = s.statistic#
  where s.sid = sys_context('USERENV','SID')
    and n.name in ('physical read bytes','session logical reads');
end;
/

select
  (:prb_after - :prb_before) as delta_physical_read_bytes,
  (:slr_after - :slr_before) as delta_session_logical_reads
from dual;
実行結果
SQL> alter session set inmemory_query = enable;

Session altered.

Elapsed: 00:00:00.002
SQL> var prb_before number
r - :slr_before) as delta_session_logical_reads
from dual;^[[201~SQL> var slr_before number
SQL> begin
  2    select
  3      max(case when n.name = 'physical read bytes'   then s.value end),
  4      max(case when n.name = 'session logical reads' then s.value end)
  5    into :prb_before, :slr_before
  6    from v$sesstat s join v$statname n on n.statistic# = s.statistic#
  7    where s.sid = sys_context('USERENV','SID')
  8      and n.name in ('physical read bytes','session logical reads');
  9  end;
 10* /

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.022
SQL>
SQL> -- デモSQL(結果は30行)
SQL> select /*+ gather_plan_statistics
  2             parallel(f 8) full(f)
  3             parallel(p 8) full(p)
  4             parallel(r 8) full(r)
  5             no_result_cache
  6          */
  7         r.region_name,
  8         p.category,
  9         sum(f.amount) as sum_amount
 10  from fact_sales f
 11  join dim_region  r on r.region_id = f.region_id
 12  join dim_product p on p.prod_id   = f.prod_id
 13  where f.sale_dt >= date'2025-05-01'
 14    and f.sale_dt <  date'2025-07-01'
 15  group by r.region_name, p.category
 16  order by sum_amount desc
 17* fetch first 30 rows only;

REGION_NAME CATEGORY SUM_AMOUNT
___________ ________ ___________
REGION_100  CAT_01   54950021.57
REGION_099  CAT_50   54850089.18
REGION_098  CAT_49   54749867.81
REGION_097  CAT_48   54650005.96
REGION_096  CAT_47   54550089.65
REGION_095  CAT_46   54450035.33
REGION_094  CAT_45   54349934.09
REGION_093  CAT_44   54249968.86
REGION_092  CAT_43   54150124.27
REGION_091  CAT_42   54050007.81
REGION_090  CAT_41   53949878.89
REGION_089  CAT_40    53849952.7
REGION_088  CAT_39    53749973.5
REGION_087  CAT_38   53650081.76
REGION_086  CAT_37   53549950.97
REGION_085  CAT_36   53449992.04
REGION_084  CAT_35   53350022.29
REGION_083  CAT_34   53249868.64
REGION_082  CAT_33   53150025.78
REGION_081  CAT_32    53050125.4
REGION_080  CAT_31   52950155.09
REGION_079  CAT_30   52849982.15
REGION_078  CAT_29   52750038.22
REGION_077  CAT_28   52650104.43
REGION_076  CAT_27   52549911.77
REGION_075  CAT_26   52450047.17
REGION_074  CAT_25   52349919.56
REGION_073  CAT_24   52250070.28
REGION_072  CAT_23   52150014.54
REGION_071  CAT_22    52049971.3

30 rows selected.

Elapsed: 00:00:00.137
SQL>
SQL> select * from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST +IOSTATS'));

PLAN_TABLE_OUTPUT
__________________________________________________________________________________________________________________________________________________________________
SQL_ID  cdmv00926pnnx, child number 8
-------------------------------------
select /*+ gather_plan_statistics            parallel(f 8) full(f)
      parallel(p 8) full(p)            parallel(r 8) full(r)
no_result_cache         */        r.region_name,        p.category,
   sum(f.amount) as sum_amount from fact_sales f join dim_region  r on
r.region_id = f.region_id join dim_product p on p.prod_id   = f.prod_id
where f.sale_dt >= date'2025-05-01'   and f.sale_dt <  date'2025-07-01'
group by r.region_name, p.category order by sum_amount desc fetch first
30 rows only

Plan hash value: 3727651337

------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                            | Name        | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Reads  |  OMem |  1Mem | Used-Mem |
------------------------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                                     |             |      1 |        |     30 |00:00:00.09 |      44 |      2 |       |       |          |
|*  1 |  COUNT STOPKEY                                       |             |      1 |        |     30 |00:00:00.09 |      44 |      2 |       |       |          |
|   2 |   PX COORDINATOR                                     |             |      1 |        |     30 |00:00:00.09 |      44 |      2 |  9216 |  9216 | 8192  (0)|
|   3 |    PX SEND QC (ORDER)                                | :TQ10006    |      0 |    100 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|   4 |     VIEW                                             |             |      0 |    100 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|*  5 |      SORT ORDER BY STOPKEY                           |             |      0 |    100 |      0 |00:00:00.01 |       0 |      0 | 18432 | 18432 | 2048  (0)|
|   6 |       PX RECEIVE                                     |             |      0 |     30 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|   7 |        PX SEND RANGE                                 | :TQ10005    |      0 |     30 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|*  8 |         SORT ORDER BY STOPKEY                        |             |      0 |     30 |      0 |00:00:00.01 |       0 |      0 | 18432 | 18432 | 2048  (0)|
|   9 |          HASH GROUP BY                               |             |      0 |    100 |      0 |00:00:00.01 |       0 |      0 |  1041K|  1041K| 1448K (0)|
|  10 |           PX RECEIVE                                 |             |      0 |    100 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|  11 |            PX SEND HASH                              | :TQ10004    |      0 |    100 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|  12 |             HASH GROUP BY                            |             |      0 |    100 |      0 |00:00:00.01 |       0 |      0 |   974K|   974K|          |
|* 13 |              HASH JOIN                               |             |      0 |    100 |      0 |00:00:00.01 |       0 |      0 |  3666K|  1834K| 1371K (0)|
|  14 |               JOIN FILTER CREATE                     | :BF0000     |      0 |    100 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|  15 |                PX RECEIVE                            |             |      0 |    100 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|  16 |                 PX SEND BROADCAST                    | :TQ10003    |      0 |    100 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|* 17 |                  HASH JOIN BUFFERED                  |             |      0 |    100 |      0 |00:00:00.01 |       0 |      0 |  3217K|  2681K| 4259K (0)|
|  18 |                   PX RECEIVE                         |             |      0 |    100 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|  19 |                    PX SEND HYBRID HASH               | :TQ10001    |      0 |    100 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|  20 |                     STATISTICS COLLECTOR             |             |      0 |        |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|  21 |                      VIEW                            | VW_GBC_11   |      0 |    100 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|  22 |                       HASH GROUP BY                  |             |      0 |    100 |      0 |00:00:00.01 |       0 |      0 |  1232K|  1232K| 1438K (0)|
|  23 |                        PX RECEIVE                    |             |      0 |    100 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|  24 |                         PX SEND HASH                 | :TQ10000    |      0 |    100 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|  25 |                          HASH GROUP BY               |             |      0 |    100 |      0 |00:00:00.01 |       0 |      0 |  3692K|  1516K| 1754K (0)|
|  26 |                           PX BLOCK ITERATOR          |             |      0 |     10M|      0 |00:00:00.01 |       0 |      0 |       |       |          |
|* 27 |                            TABLE ACCESS INMEMORY FULL| FACT_SALES  |      0 |     10M|      0 |00:00:00.01 |       0 |      0 |       |       |          |
|  28 |                   PX RECEIVE                         |             |      0 |    100 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|  29 |                    PX SEND HYBRID HASH               | :TQ10002    |      0 |    100 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|  30 |                     PX BLOCK ITERATOR                |             |      0 |    100 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|* 31 |                      TABLE ACCESS INMEMORY FULL      | DIM_REGION  |      0 |    100 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|  32 |               JOIN FILTER USE                        | :BF0000     |      0 |   5000 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|  33 |                PX BLOCK ITERATOR                     |             |      0 |   5000 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
|* 34 |                 TABLE ACCESS INMEMORY FULL           | DIM_PRODUCT |      0 |   5000 |      0 |00:00:00.01 |       0 |      0 |       |       |          |
------------------------------------------------------------------------------------------------------------------------------------------------------------------

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

   1 - filter(ROWNUM<=30)
   5 - filter(ROWNUM<=30)
   8 - filter(ROWNUM<=30)
  13 - access("P"."PROD_ID"="ITEM_2")
  17 - access("R"."REGION_ID"="ITEM_1")
  27 - inmemory(:Z>=:Z AND :Z<=:Z)
  31 - inmemory(:Z>=:Z AND :Z<=:Z)
  34 - inmemory(:Z>=:Z AND :Z<=:Z AND SYS_OP_BLOOM_FILTER(:BF0000,"P"."PROD_ID"))
       filter(SYS_OP_BLOOM_FILTER(:BF0000,"P"."PROD_ID"))

Note
-----
   - dynamic statistics used: dynamic sampling (level=AUTO (SYSTEM))
   - Degree of Parallelism is 8 because of table property
   - statistics feedback used for this statement


72 rows selected.

Elapsed: 00:00:00.047
SQL>
SQL> var prb_after number
SQL> var slr_after number
SQL> begin
  2    select
  3      max(case when n.name = 'physical read bytes'   then s.value end),
  4      max(case when n.name = 'session logical reads' then s.value end)
  5    into :prb_after, :slr_after
  6    from v$sesstat s join v$statname n on n.statistic# = s.statistic#
  7    where s.sid = sys_context('USERENV','SID')
  8      and n.name in ('physical read bytes','session logical reads');
  9  end;
 10* /

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.022
SQL>
SQL> select
  2    (:prb_after - :prb_before) as delta_physical_read_bytes,
  3    (:slr_after - :slr_before) as delta_session_logical_reads
  4* from dual;

DELTA_PHYSICAL_READ_BYTES DELTA_SESSION_LOGICAL_READS
_________________________ ___________________________
                   139264                    10003032

Elapsed: 00:00:00.003
SQL>

■ 結果

項目 IM OFF
(Diskアクセス)
IM ON
(In-Memoryアクセス)
Elapsed 02:41.7 00:00.1
delta physical read bytes 81,936,908,288(約76.3GB) 139,264(約136KB)
圧縮(Disk→IM) P05:38.15GB→0.44GB
P06:38.15GB→0.44GB
(各パーティション87.23倍圧縮)
同左

● 圧縮率(Disk vs In-Memory)

今回、パーティション P05P06 は、それぞれ Disk 上では 38.15GB だったのに対し、In-Memory 上では 0.44GB まで圧縮されました。
つまり、1 パーティションあたり約 87 倍の圧縮率となっています。

2つの パーティション合計で見ると、Disk 上では約 76.3GB のデータが、In-Memory 上では約 0.88GB に収まっていることが確認できました。

比較
V$IM_SEGMENTS(FACT_SALESのP05/P06)より
P05:Disk 38.15GB → IM 0.44GB(87.23x)
P06:Disk 38.15GB → IM 0.44GB(87.23x)

● In-Memory=OFF(Disk読み) vs In-Memory=ON(In-Memory読み)の測定結果

実行時間は、In-Memory OFF では 161.706 秒、In-Memory ON では 0.137 秒でした。
今回の条件では、約 1,180 倍の高速化が確認できました。

また、物理 I/O についても、In-Memory OFF では約 76.3GB の読み取りが発生した一方で、In-Memory ON では 136KB 程度に抑えられていました。

・ 実行時間(Elapsed)
約 1,180倍 高速化(161.706 / 0.137 ≒ 1180)

比較
In-Memory=OFF:00:02:41.706(= 161.706秒)
In-Memory=ON :00:00:00.137(= 0.137秒)

・ 物理I/O(delta_physical_read_bytes)
IM OFFは約76GBをディスクから読み、IM ONはほぼ0

比較
In-Memory=OFF:81,936,908,288 bytes ≒ 76.3GB 読み取り
In-Memory=ON :139,264 bytes ≒ 136KB 読み取り

■ まとめ

回は Oracle AI Database In-Memory を有効化し、Disk 読み取り時と In-Memory 読み取り時の差を比較してみました。

その結果、

  • 実行時間は 161.706 秒 → 0.137 秒
  • 物理読み取りは 約 76.3GB → 約 136KB
  • データサイズは 38.15GB/partition → 0.44GB/partition

となり、In-Memory によって大幅な高速化と高い圧縮効果を確認できました。
また、In-Memory はテーブル単位だけでなく、パーティション単位でも柔軟に設定できるため、必要なデータだけを効率よくメモリに載せる運用が可能です。
分析クエリを高速化したい場面では、非常に強力な選択肢になりそうです。

■ 参考

■ 技術解説

■ おまけ

今回の内容を、ずんだもん達に紹介してもらう漫画も作ってみました。 技術記事の補足として、少しでも楽しく読んでもらえたらうれしいです。
おまけ.png

※ 本漫画は筆者による非公式の二次創作です。
※ 使用キャラクター:ずんだもん / 四国めたん / 春日部つむぎ
※ キャラクターの権利は各権利元に帰属します。
※ クレジット
 - ずんだもん / 四国めたん:東北ずん子・ずんだもんプロジェクト関連ガイドラインに基づいて利用
 - 春日部つむぎ:公式利用規約に基づいて利用

16
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?