【Oracle】テーブル圧縮の設定方法|BASIC・OLTP・HCC の違い・圧縮率・ライセンス・既存テーブルの圧縮手順まで解説

【Oracle】テーブル圧縮の設定方法|BASIC・OLTP・HCC の違い・圧縮率・ライセンス・既存テーブルの圧縮手順まで解説 Oracle

Oracle のテーブル圧縮は、データの物理格納サイズを削減してストレージコストを下げ、I/O を減らすことでクエリパフォーマンスを改善する機能です。圧縮方式は BASIC(無料)OLTP(Advanced Compression)HCC(Exadata / ZFS 向け)の 3 種類があり、用途とライセンスによって使い分けます。

本記事では、3 つの圧縮方式の違い、圧縮率とパフォーマンスCREATE TABLE / ALTER TABLE での設定既存テーブルの圧縮手順まで解説します。

この記事でわかること
・BASIC / OLTP / HCC の 3 方式の違いと使い分け
・ライセンス要件(無料で使える範囲と有償オプション)
・CREATE TABLE 時の圧縮設定
・既存テーブルの圧縮(ALTER TABLE MOVE COMPRESS)
・パーティション単位の圧縮
・圧縮状態の確認 SQL
・圧縮のパフォーマンスへの影響
スポンサーリンク

3 つの圧縮方式の比較

方式 キーワード ライセンス 圧縮率 DML への影響 適するケース
BASIC 圧縮 COMPRESS BASIC / ROW STORE COMPRESS BASIC 無料(EE/SE 両方) 2〜4 倍 ダイレクトパスロード時のみ圧縮。通常 INSERT では圧縮されない バルクロード(CTAS / INSERT APPEND)で作成するテーブル
OLTP 圧縮 ROW STORE COMPRESS ADVANCED Advanced Compression Option(有償) 2〜4 倍 通常の INSERT / UPDATE も圧縮 OLTP ワークロード(頻繁な DML がある本番テーブル)
HCC COLUMN STORE COMPRESS FOR QUERY / ARCHIVE Exadata / ZFS / ODA 専用 6〜15 倍 行単位の UPDATE が非常に遅い アーカイブデータ / DWH(参照のみ / バッチ更新のみ)
無料で使えるのは BASIC 圧縮のみ
BASIC 圧縮は Enterprise Edition / Standard Edition ともに追加ライセンスなしで使えます。ただし BASIC は「ダイレクトパスロード」(CTAS / INSERT /*+ APPEND */ / SQL*Loader DIRECT=TRUE)でのみ圧縮されます。通常の INSERT 文では圧縮されません。OLTP 圧縮は通常の DML でも圧縮されますが Advanced Compression Option ライセンスが必要です。

BASIC 圧縮(無料)

SQL(BASIC 圧縮でテーブルを作成)
-- CREATE TABLE 時に BASIC 圧縮を指定
CREATE TABLE orders_archive (
    order_id   NUMBER,
    order_date DATE,
    amount     NUMBER
) COMPRESS BASIC;

-- 11g 以降の正式構文
CREATE TABLE orders_archive (
    order_id   NUMBER,
    order_date DATE,
    amount     NUMBER
) ROW STORE COMPRESS BASIC;

-- CTAS で圧縮テーブルを作成(データも圧縮される)
CREATE TABLE orders_compressed
    COMPRESS BASIC
AS SELECT * FROM orders;
BASIC 圧縮は通常の INSERT では圧縮されない
INSERT INTO orders_archive VALUES (...) のような通常の INSERT では、データは非圧縮で格納されます。BASIC 圧縮が適用されるのは以下のケースのみです。
・CTAS(CREATE TABLE AS SELECT)
・INSERT /*+ APPEND */ … SELECT …
・SQL*Loader DIRECT=TRUE
・Data Pump Import

OLTP 圧縮(Advanced Compression Option)

SQL(OLTP 圧縮)
-- OLTP 圧縮: 通常の INSERT / UPDATE でも圧縮される
CREATE TABLE orders_oltp (
    order_id   NUMBER,
    order_date DATE,
    amount     NUMBER
) ROW STORE COMPRESS ADVANCED;

-- 通常の INSERT でも圧縮が適用される
INSERT INTO orders_oltp VALUES (1, SYSDATE, 5000);
-- → ブロック内に十分なデータが溜まるとバッチ圧縮される
OLTP 圧縮の仕組み
OLTP 圧縮では、ブロック内のデータが一定量溜まった時点でバッチ的に圧縮されます。INSERT 直後は非圧縮状態で、ブロックが埋まると圧縮処理が走ります。このため、単一行の INSERT では圧縮効果が見えにくいですが、大量 INSERT や時間経過で効果が表れます。

HCC(Hybrid Columnar Compression)

SQL(HCC: Exadata / ZFS 環境のみ)
-- HCC QUERY LOW: 高速クエリ向け(圧縮率中)
CREATE TABLE sales_dw (
    sale_id   NUMBER,
    sale_date DATE,
    amount    NUMBER
) COLUMN STORE COMPRESS FOR QUERY LOW;

-- HCC QUERY HIGH: 高圧縮クエリ向け
-- COLUMN STORE COMPRESS FOR QUERY HIGH

-- HCC ARCHIVE LOW: アーカイブ向け(高圧縮)
-- COLUMN STORE COMPRESS FOR ARCHIVE LOW

-- HCC ARCHIVE HIGH: 最大圧縮(参照頻度が非常に低いデータ)
-- COLUMN STORE COMPRESS FOR ARCHIVE HIGH
HCC レベル 圧縮率 用途
QUERY LOW 6〜8 倍 DWH の頻繁にクエリされるファクトテーブル
QUERY HIGH 8〜12 倍 DWH の中頻度クエリテーブル
ARCHIVE LOW 10〜15 倍 過去データのアーカイブ(参照は稀)
ARCHIVE HIGH 15〜50 倍 法的保管要件のデータ(ほぼ参照しない)
HCC は Exadata / ZFS / ODA 専用
HCC は Oracle Exadata、Oracle ZFS Storage Appliance、Oracle Database Appliance でのみ使用可能です。一般的なストレージでは HCC を指定してもOLTP 圧縮として動作するか、エラーになります。

既存テーブルの圧縮

ALTER TABLE MOVE COMPRESS

SQL(既存テーブルを圧縮)
-- 既存テーブルを BASIC 圧縮に変更
ALTER TABLE orders MOVE COMPRESS BASIC;

-- OLTP 圧縮に変更
ALTER TABLE orders MOVE ROW STORE COMPRESS ADVANCED;

-- 12c 以降: MOVE ONLINE で DML を止めずに圧縮
ALTER TABLE orders MOVE ONLINE ROW STORE COMPRESS ADVANCED;

-- MOVE 後のインデックス再構築(通常 MOVE の場合のみ必要)
ALTER INDEX idx_orders_date REBUILD;
-- MOVE ONLINE なら REBUILD 不要(12c 以降)

圧縮を解除する

SQL(圧縮の解除: NOCOMPRESS)
-- 今後のデータを非圧縮にする(既存データは圧縮のまま)
ALTER TABLE orders NOCOMPRESS;

-- 既存データも含めて完全に非圧縮にする
ALTER TABLE orders MOVE NOCOMPRESS;
ALTER TABLE NOCOMPRESS は今後の INSERT だけに影響
ALTER TABLE t NOCOMPRESS は「テーブルの圧縮属性」を変更するだけで、既に圧縮済みのブロックは圧縮のまま残ります。全データを非圧縮にするには MOVE NOCOMPRESS が必要です。

表領域レベルでの圧縮設定

SQL(表領域のデフォルト圧縮を設定)
-- 表領域のデフォルトを BASIC 圧縮に設定
CREATE TABLESPACE archive_ts
    DATAFILE '/oracle/oradata/archive01.dbf' SIZE 5G
    DEFAULT COMPRESS BASIC;

-- OLTP 圧縮をデフォルトに
CREATE TABLESPACE oltp_ts
    DATAFILE '/oracle/oradata/oltp01.dbf' SIZE 5G
    DEFAULT ROW STORE COMPRESS ADVANCED;

-- この表領域に CREATE TABLE すると自動的に圧縮が適用される
-- テーブルごとに個別に COMPRESS / NOCOMPRESS で上書き可能

パーティション単位の圧縮

SQL(パーティションごとに異なる圧縮を設定)
-- 最新パーティション: OLTP 圧縮(DML が多い)
-- 古いパーティション: BASIC 圧縮(参照のみ)
CREATE TABLE sales (
    sale_id   NUMBER,
    sale_date DATE,
    amount    NUMBER
) PARTITION BY RANGE (sale_date) (
    PARTITION p_2024 VALUES LESS THAN (DATE '2025-01-01')
        COMPRESS BASIC,         -- 過去データ: BASIC
    PARTITION p_2025 VALUES LESS THAN (DATE '2026-01-01')
        ROW STORE COMPRESS ADVANCED,  -- 現行: OLTP
    PARTITION p_max  VALUES LESS THAN (MAXVALUE)
        NOCOMPRESS               -- 最新: 非圧縮
);
SQL(古いパーティションを後から圧縮)
-- 古いパーティションを BASIC 圧縮に変更
ALTER TABLE sales MOVE PARTITION p_2024 COMPRESS BASIC;

-- 12c 以降: ONLINE で圧縮
ALTER TABLE sales MOVE PARTITION p_2024 ONLINE COMPRESS BASIC;
ILM(Information Lifecycle Management)パターン
パーティションの年齢に応じて圧縮レベルを段階的に変更する「ライフサイクル管理」は大規模 DB の定番パターンです。
・作成直後: NOCOMPRESS(DML が活発)
・3 か月後: OLTP 圧縮(DML が減少)
・1 年後: BASIC 圧縮(参照のみ)
・3 年後: HCC(Exadata の場合)/ READ ONLY

圧縮状態の確認 SQL

SQL(テーブルの圧縮設定を確認)
-- テーブルの圧縮設定
SELECT table_name, compression, compress_for
FROM user_tables
WHERE table_name = 'ORDERS';
-- compression: ENABLED / DISABLED
-- compress_for: BASIC / ADVANCED / QUERY HIGH 等

-- 全テーブルの圧縮状態一覧
SELECT table_name, compression, compress_for,
       ROUND(s.bytes/1024/1024, 1) AS size_mb
FROM user_tables t
JOIN user_segments s ON t.table_name = s.segment_name AND s.segment_type = 'TABLE'
ORDER BY compression DESC, s.bytes DESC;
SQL(パーティションごとの圧縮設定)
SELECT table_name, partition_name, compression, compress_for
FROM user_tab_partitions
WHERE table_name = 'SALES'
ORDER BY partition_position;
SQL(圧縮率の推定: 圧縮前後のサイズ比較)
-- 圧縮前のテーブルサイズ
SELECT ROUND(bytes/1024/1024, 1) AS size_mb FROM user_segments
WHERE segment_name = 'ORDERS' AND segment_type = 'TABLE';

-- 圧縮後のテーブルサイズ(MOVE COMPRESS 後に再確認)
-- 例: 500 MB → 180 MB = 圧縮率 2.8 倍

-- DBMS_COMPRESSION で圧縮率を事前推定(12c 以降)
SET SERVEROUTPUT ON
DECLARE
    v_blkcnt_cmp   PLS_INTEGER;
    v_blkcnt_uncmp PLS_INTEGER;
    v_row_cmp      PLS_INTEGER;
    v_row_uncmp    PLS_INTEGER;
    v_cmp_ratio    NUMBER;
    v_cmp_type     VARCHAR2(200);
BEGIN
    DBMS_COMPRESSION.GET_COMPRESSION_RATIO(
        scratchtbsname => 'USERS',
        ownname        => USER,
        objname        => 'ORDERS',
        subobjname     => NULL,
        comptype       => DBMS_COMPRESSION.COMP_ADVANCED,
        blkcnt_cmp     => v_blkcnt_cmp,
        blkcnt_uncmp   => v_blkcnt_uncmp,
        row_cmp        => v_row_cmp,
        row_uncmp      => v_row_uncmp,
        cmp_ratio      => v_cmp_ratio,
        comptype_str   => v_cmp_type
    );
    DBMS_OUTPUT.PUT_LINE('Compression type: ' || v_cmp_type);
    DBMS_OUTPUT.PUT_LINE('Compression ratio: ' || ROUND(v_cmp_ratio, 2) || 'x');
END;
/

圧縮のパフォーマンスへの影響

操作 BASIC 圧縮 OLTP 圧縮
SELECT(フルスキャン) 高速化(読み込みブロック数が減る) 高速化
SELECT(インデックススキャン) 変化なし〜微速化 変化なし〜微速化
INSERT(通常) 圧縮されない(非圧縮で格納) 若干の CPU オーバーヘッド
INSERT(APPEND / CTAS) 圧縮される(高速) 圧縮される
UPDATE 非圧縮行に変換される場合あり(行移行のリスク) バッチ圧縮で対応
DELETE 影響なし 影響なし
圧縮は SELECT を高速化し、DML には若干のオーバーヘッド
圧縮テーブルのフルスキャンは読み込みブロック数が 2〜4 分の 1 になるため劇的に速くなることがあります。一方、INSERT / UPDATE では圧縮・解凍の CPU コストが若干増加します。参照が多く更新が少ないテーブルに圧縮を適用するのが最も効果的です。

ライセンス要件のまとめ

機能 ライセンス EE / SE
BASIC 圧縮(COMPRESS BASIC) 無料 EE + SE 両方
OLTP 圧縮(COMPRESS ADVANCED) Advanced Compression Option EE のみ
HCC(COLUMN STORE COMPRESS) Exadata / ZFS / ODA のライセンスに含まれる EE + 専用ハードウェア
DBMS_COMPRESSION(圧縮率推定) Advanced Compression Option EE のみ
ライセンス違反に注意
OLTP 圧縮(ROW STORE COMPRESS ADVANCED)を Advanced Compression Option のライセンスなしに使用するとライセンス違反になります。V$OPTION でライセンスの有効状態を確認してから使用してください。
SELECT VALUE FROM V$OPTION WHERE PARAMETER = 'Advanced Compression';

実務パターン集

パターン(1): アーカイブテーブルを BASIC 圧縮(無料)

SQL
-- 過去データを圧縮テーブルに移行
CREATE TABLE orders_2023_archive
    COMPRESS BASIC
AS SELECT * FROM orders WHERE order_date < DATE '2024-01-01';

-- 元テーブルから削除
DELETE FROM orders WHERE order_date < DATE '2024-01-01';
COMMIT;

パターン(2): 既存テーブルを OLTP 圧縮(12c+)

SQL
-- MOVE ONLINE で無停止圧縮
ALTER TABLE orders MOVE ONLINE ROW STORE COMPRESS ADVANCED;

-- 圧縮効果の確認
SELECT ROUND(bytes/1024/1024, 1) AS size_mb FROM user_segments
WHERE segment_name = 'ORDERS';

パターン(3): パーティションの段階的圧縮

SQL
-- 1 年前のパーティションを BASIC 圧縮に変更
ALTER TABLE sales MOVE PARTITION p_2024 ONLINE COMPRESS BASIC;

-- 統計再収集
EXEC DBMS_STATS.GATHER_TABLE_STATS(USER, 'SALES', PARTNAME => 'P_2024');

パターン(4): 圧縮前に圧縮率を事前推定

SQL
-- DBMS_COMPRESSION で推定(本記事の DBMS_COMPRESSION セクション参照)
-- 推定結果が 2 倍以上なら圧縮する価値あり

よくある質問

QBASIC 圧縮は Standard Edition でも使えますか?
A使えます。BASIC 圧縮(COMPRESS BASIC)は追加ライセンスなしで Enterprise Edition / Standard Edition の両方で利用可能です。ただし通常の INSERT では圧縮されず、ダイレクトパスロード(CTAS / APPEND / SQL*Loader DIRECT)時のみ圧縮される点に注意してください。
Q圧縮するとバックアップサイズも小さくなりますか?
Aはい。RMAN バックアップは圧縮されたブロックをそのままバックアップするため、バックアップファイルのサイズも縮小されます。さらに RMAN の圧縮(BACKUP AS COMPRESSED BACKUPSET)と組み合わせるとより小さくなります。
Q圧縮テーブルに UPDATE すると遅くなりますか?
ABASIC 圧縮では UPDATE で行が非圧縮に変換され、行移行(Row Migration)が発生して遅くなる場合があります。OLTP 圧縮ではブロック単位でバッチ圧縮されるため影響は小さいですが、頻繁な UPDATE には向きません。
QALTER TABLE COMPRESS だけでは既存データは圧縮されませんか?
AALTER TABLE t COMPRESS BASIC はテーブルの圧縮属性を変更するだけで、既存データは圧縮されません。既存データを圧縮するには ALTER TABLE t MOVE COMPRESS BASIC でテーブルを再配置する必要があります。
Q圧縮テーブルのフルスキャンは本当に速くなりますか?
Aはい。圧縮によりブロック数が 2〜4 分の 1 になるため、フルスキャンの I/O が大幅に削減されます。特に HDD ベースのストレージでは2〜3 倍の速度改善が見られることがあります。SSD 環境でも I/O 量の削減は有効です。
Q圧縮を解除すると元のサイズに戻りますか?
AALTER TABLE t MOVE NOCOMPRESS で非圧縮に戻すと、テーブルサイズは元の(圧縮前の)サイズに戻ります。十分な表領域の空きがあることを確認してから実行してください。

まとめ

テーブル圧縮の要点をまとめます。

やりたいこと SQL
BASIC 圧縮でテーブルを作成(無料) CREATE TABLE t (…) COMPRESS BASIC
OLTP 圧縮でテーブルを作成 CREATE TABLE t (…) ROW STORE COMPRESS ADVANCED
既存テーブルを圧縮(11g) ALTER TABLE t MOVE COMPRESS BASIC + ALTER INDEX … REBUILD
既存テーブルを圧縮(12c+) ALTER TABLE t MOVE ONLINE ROW STORE COMPRESS ADVANCED
パーティション単位で圧縮 ALTER TABLE t MOVE PARTITION p ONLINE COMPRESS BASIC
圧縮状態の確認 SELECT compression, compress_for FROM user_tables WHERE table_name = ‘T’
圧縮率を事前推定 DBMS_COMPRESSION.GET_COMPRESSION_RATIO
圧縮を解除 ALTER TABLE t MOVE NOCOMPRESS

表領域の管理全般は「表領域(Tablespace)完全ガイド」、断片化の解消は「表領域の断片化を解消する方法」も併せて参照してください。