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 圧縮は Enterprise Edition / Standard Edition ともに追加ライセンスなしで使えます。ただし BASIC は「ダイレクトパスロード」(CTAS / INSERT /*+ APPEND */ / SQL*Loader DIRECT=TRUE)でのみ圧縮されます。通常の INSERT 文では圧縮されません。OLTP 圧縮は通常の DML でも圧縮されますが Advanced Compression Option ライセンスが必要です。
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;
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)
-- 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 圧縮では、ブロック内のデータが一定量溜まった時点でバッチ的に圧縮されます。INSERT 直後は非圧縮状態で、ブロックが埋まると圧縮処理が走ります。このため、単一行の INSERT では圧縮効果が見えにくいですが、大量 INSERT や時間経過で効果が表れます。
HCC(Hybrid Columnar Compression)
-- 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 は Oracle Exadata、Oracle ZFS Storage Appliance、Oracle Database Appliance でのみ使用可能です。一般的なストレージでは HCC を指定してもOLTP 圧縮として動作するか、エラーになります。
既存テーブルの圧縮
ALTER TABLE MOVE COMPRESS
-- 既存テーブルを 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 以降)
圧縮を解除する
-- 今後のデータを非圧縮にする(既存データは圧縮のまま) ALTER TABLE orders NOCOMPRESS; -- 既存データも含めて完全に非圧縮にする ALTER TABLE orders MOVE NOCOMPRESS;
ALTER TABLE t NOCOMPRESS は「テーブルの圧縮属性」を変更するだけで、既に圧縮済みのブロックは圧縮のまま残ります。全データを非圧縮にするには MOVE NOCOMPRESS が必要です。表領域レベルでの圧縮設定
-- 表領域のデフォルトを 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 で上書き可能
パーティション単位の圧縮
-- 最新パーティション: 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 -- 最新: 非圧縮
);
-- 古いパーティションを BASIC 圧縮に変更 ALTER TABLE sales MOVE PARTITION p_2024 COMPRESS BASIC; -- 12c 以降: ONLINE で圧縮 ALTER TABLE sales MOVE PARTITION p_2024 ONLINE COMPRESS BASIC;
パーティションの年齢に応じて圧縮レベルを段階的に変更する「ライフサイクル管理」は大規模 DB の定番パターンです。
・作成直後: NOCOMPRESS(DML が活発)
・3 か月後: OLTP 圧縮(DML が減少)
・1 年後: BASIC 圧縮(参照のみ)
・3 年後: HCC(Exadata の場合)/ READ ONLY
圧縮状態の確認 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;
SELECT table_name, partition_name, compression, compress_for FROM user_tab_partitions WHERE table_name = 'SALES' ORDER BY partition_position;
-- 圧縮前のテーブルサイズ
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 | 影響なし | 影響なし |
圧縮テーブルのフルスキャンは読み込みブロック数が 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 圧縮(無料)
-- 過去データを圧縮テーブルに移行
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+)
-- 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): パーティションの段階的圧縮
-- 1 年前のパーティションを BASIC 圧縮に変更 ALTER TABLE sales MOVE PARTITION p_2024 ONLINE COMPRESS BASIC; -- 統計再収集 EXEC DBMS_STATS.GATHER_TABLE_STATS(USER, 'SALES', PARTNAME => 'P_2024');
パターン(4): 圧縮前に圧縮率を事前推定
-- DBMS_COMPRESSION で推定(本記事の DBMS_COMPRESSION セクション参照) -- 推定結果が 2 倍以上なら圧縮する価値あり
よくある質問
ALTER TABLE t COMPRESS BASIC はテーブルの圧縮属性を変更するだけで、既存データは圧縮されません。既存データを圧縮するには ALTER TABLE t MOVE COMPRESS BASIC でテーブルを再配置する必要があります。ALTER 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)完全ガイド」、断片化の解消は「表領域の断片化を解消する方法」も併せて参照してください。

