すべてのプロダクト
Search
ドキュメントセンター

PolarDB:GanosBase のフルスペースデータ多態 (ホット/コールド) 階層化ストレージの分析とベストプラクティス

最終更新日:Mar 29, 2026

空間データおよび時空間データがテラバイトやペタバイト規模に増大するにつれて、すべてのデータを高性能ディスクに保存すると、特に履歴データや補助データへのアクセスが稀な場合に、コストが高くなります。GanosBase の多態階層化ストレージを使用すると、コールドデータ (期限切れのパーティション、ラージオブジェクトフィールド、ラスターブロックデータなど) を Object Storage Service (OSS) に移動させ、ホットデータとインデックスは Elastic Block Storage (EBS) ディスクに保持できます。ディスク上のマテリアライズドキャッシュレイヤーが、コールドデータへのアクセスを自動的に高速化します。コールドデータに対する CRUD 操作、インデックススキャン、結合クエリに SQL の書き換えは不要です。その結果、透過的なデータアクセスを維持したまま、ストレージコストを最大 90% 削減できます。

仕組み

コールドデータは小さなブロックに分割、圧縮され、OSS に書き込まれます。データベースディスク上に構築されたマテリアライズドキャッシュレイヤーが、コールドデータに対する頻繁な読み書きを処理し、ブロックのアクセスパターンに基づいて自動的に階層化します。

主要な仕組み:

仕組み詳細
圧縮コールドデータは OSS に書き込まれる前に圧縮されます。一般データ: 20%~40% の圧縮率。時空間データ: 60%~70%。ワークロード全体の平均: 50%。
マテリアライズドキャッシュデータブロックのアクセスパターンに基づく自動階層化。更新および挿入パフォーマンス: ディスクの 90%。ポイントクエリパフォーマンス: ディスクの 80%。
データバージョニングコピーオンライト (COW) メカニズムを使用します。最初のスナップショット以降は、更新されたブロックのみが複製されるため、スナップショットは最小限のコストで数秒で完了します。
信頼性OSS は 99.9999999999% のデータ信頼性と 99.995% のデータの可用性を提供し、冗長性のために LRS と ZRS のオプションがあります。
透過的なアクセスコールドデータに対する CRUD 操作、インデックススキャン、結合クエリに SQL の書き換えは不要です。

ストレージコストの比較

以下の表は、100 GB のデータに対する PolarDB ディスク (PSL4) と OSS の比較です:

ディスク (PSL4)多態階層化ストレージ (OSS)
課金レート0.238 USD/GB/月LRS: 0.0173 USD/GB/月、ZRS: 0.0232 USD/GB/月
圧縮率0%50%
100 GB あたりの月額コスト0.238 × 100 GB = 23.8 USD

0.238 × 100 GB = 23.8 USD

LRS: 0.0173 × 50 GB + 0.238 × 1 GB (キャッシュ) = 1.103 USD、ZRS: 0.0232 × 50 GB + 0.238 × 1 GB (キャッシュ) = 1.398 USD
  • ローカル冗長:

    • OSS: 0.0173 × (100 GB × 50%) = 0.865 USD

    • キャッシュ: 0.238 × 1 GB = 0.238 USD

    合計: 1.103 USD

  • ゾーン冗長:

    • OSS: 0.0232 × (100 GB × 50%) = 1.16 USD

    • キャッシュ: 0.238 × 1 GB = 0.238 USD

    合計: 1.398 USD

OSS のストレージコストは、ディスクストレージコストの 10% 未満です。

サポートされるストレージの組み合わせ

多態階層化ストレージは、いくつかのストレージの組み合わせをサポートしています:

  • すべてのテーブルデータを OSS に保存し、インデックスをディスク上に保持する — インデックスのアクセスパフォーマンスを維持しながらコストを削減します。

  • ラージオブジェクト (LOB) フィールド (例: BLOBTEXTJSONJSONBANYARRAY、または時空間データ型) のみを OSS に保存し、残りのフィールドをディスク上に保持します。

  • 期限切れのパーティションを OSS に保存し、ホットパーティションをディスク上に保持します。さらに、コールドパーティションのインデックスを OSS に移動したり、ホットパーティションのインデックスをディスク上に保持したりするなど、さらなるカスタマイズが可能です。

image \(2\).png

制限事項

階層化ストレージを設定する前に、以下の制約にご注意ください:

  • 新規書き込みにのみ適用ALTER COLUMN 文を実行した後に挿入されたデータのみが OSS に移動します。既存のデータを移行するには、VACUUM FULLALTER COLUMN の後に実行します。これにより、すべてのテーブルデータが再書き込みされますが、処理中はテーブルが読み書き操作に利用できなくなり、大規模なテーブルでは時間がかかる場合があります。

  • OSS のみ: この機能は OSS、MinIO、および Hadoop 分散ファイルシステム (HDFS) をサポートするように設計されていますが、現在サポートされているのは OSS のみです。

階層化パターンの選択

最も一般的なワークロードをカバーする 3 つのパターンがあります:

パターン最適な用途階層化の方法
期限切れパーティションの自動アーカイブ月次またはその他の定期的なパーティションを持つ時系列データpg_cron + polar_alter_subpartition_to_oss
LOB フィールドの OSS への移動大きなテキスト、JSON、または空間フィールドを持つ非パーティション化テーブルALTER COLUMN ... SET (storage_type='oss')
ラスターブロックデータの OSS へのアーカイブリアルタイム要件のないリモートセンシングまたは地理空間分析カスタムストアドプロシージャ + ALTER TABLE ... SET TABLESPACE oss

期限切れパーティションの自動アーカイブ

このパターンは、古いパーティションへのアクセスが稀な時系列ワークロードに適しています。以下の例では、軌道データが月ごとにパーティション化され、3 か月より古いパーティションは自動的に OSS に移動されます。

前提条件

開始する前に、以下を確認してください:

  • PolarDB for PostgreSQL (Compatible with Oracle) クラスター

  • 特権アカウントでの postgres データベースへのアクセス

拡張機能と定期アーカイブの設定

  1. テストデータベースを作成します。詳細については、「データベースの作成」をご参照ください。次に、パーティションテーブルを作成し、テストデータを挿入します:

    -- パーティションテーブルを作成
    CREATE TABLE traj(
      tr_id serial,
      tr_lon float,
      tr_lat float,
      tr_time timestamp(6)
    )PARTITION BY RANGE (tr_time);
    
    CREATE TABLE traj_202301 PARTITION OF traj
        FOR VALUES FROM ('2023-01-01') TO ('2023-02-01');
    CREATE TABLE traj_202302 PARTITION OF traj
        FOR VALUES FROM ('2023-02-01') TO ('2023-03-01');
    CREATE TABLE traj_202303 PARTITION OF traj
        FOR VALUES FROM ('2023-03-01') TO ('2023-04-01');
    CREATE TABLE traj_202304 PARTITION OF traj
        FOR VALUES FROM ('2023-04-01') TO ('2023-05-01');
    
    -- テストデータを挿入
    INSERT INTO traj(tr_lon,tr_lat,tr_time) values(112.35, 37.12, '2023-01-01');
    INSERT INTO traj(tr_lon,tr_lat,tr_time) values(112.35, 37.12, '2023-02-01');
    INSERT INTO traj(tr_lon,tr_lat,tr_time) values(112.35, 37.12, '2023-03-01');
    INSERT INTO traj(tr_lon,tr_lat,tr_time) values(112.35, 37.12, '2023-04-01');
    
    -- パーティションテーブルにインデックスを作成
    CREATE INDEX traj_idx on traj(tr_id);
  2. テストデータベースに polar_osfs_toolkit 拡張機能を作成します。これにより、テーブルとインデックスを OSS にアーカイブするためのユーティリティ関数が有効になります:

    CREATE EXTENSION polar_osfs_toolkit;
  3. 特権アカウントで postgres データベースに接続し、pg_cron 拡張機能を作成します:

    -- postgres データベースでは特権アカウントのみがこの文を実行できます
    CREATE EXTENSION pg_cron;

    詳細については、「pg_cron」をご参照ください。

  4. task1 という名前の定期タスクを作成し、1 分ごとに実行します。このタスクは polar_alter_subpartition_to_oss を呼び出し、3 か月より古いパーティションを OSS に移動します:

    SELECT cron.schedule_in_database('task1', '* * * * *', 'select polar_alter_subpartition_to_oss(''traj'', 3);', 'db01');

    タスク ID が返されます:

    schedule_in_database
    ----------------------
                        1

結果の検証

OSS に移動されたはずのパーティションのストレージ場所を確認します:

\d+ traj_202301

Tablespace フィールドに oss と表示されていれば、パーティションはアーカイブされています:

Table "public.traj_202301"
 Column  |              Type              | Collation | Nullable |               Default               | Storage | Compression | Stats target | Description
---------+--------------------------------+-----------+----------+-------------------------------------+---------+-------------+--------------+-------------
 tr_id   | integer                        |           | not null | nextval('traj_tr_id_seq'::regclass) | plain   |             |              |
 tr_lon  | double precision               |           |          |                                     | plain   |             |              |
 tr_lat  | double precision               |           |          |                                     | plain   |             |              |
 tr_time | timestamp(6) without time zone |           |          |                                     | plain   |             |              |
Partition of: traj FOR VALUES FROM ('2023-01-01 00:00:00') TO ('2023-02-01 00:00:00')
...
Tablespace: "oss" -- すでに OSS に保存済み
Access method: heap

定期タスクの実行履歴を確認するには、postgres データベースに接続して以下を実行します:

SELECT * FROM cron.job_run_details;

アーカイブされたパーティションは、もはやディスク領域を占有しません。それらに対する CRUD 操作は、完全な透過性を保ちながら機能し続けます。

非パーティション化テーブルの LOB フィールドの OSS への保存

ラージオブジェクト (LOB) には、BLOBTEXTJSONJSONBANYARRAY、および データ型が含まれます。このパターンは、LOB フィールドをテーブルの他の部分から分離し、小さなフィールドをディスクに保持し、LOB を OSS に移動します — SQL クエリを変更することなく、フィールドレベルでのホット/コールド分離を実現します。

LOB ストレージの OSS へのリダイレクト

  1. LOB 列を持つテーブルを作成します。この例では TEXT を使用しますが、他の LOB 型にも同じ手順が適用されます:

    CREATE TABLE blob_table(id serial, val text);
  2. val 列のストレージ場所を OSS に設定します:

    ALTER TABLE blob_table ALTER COLUMN val SET (storage_type='oss');
  3. データを挿入し、ストレージ場所を確認します:

    INSERT INTO blob_table(val) VALUES((SELECT string_agg(random()::text, ':') FROM generate_series(1, 100000)));

    val 列のデータがどこに保存されているかを確認します:

    WITH tmp AS (SELECT 'pg_toast_'||b.oid||'_'||c.attnum AS tblname FROM pg_class b, pg_attribute c WHERE b.relname='blob_table' AND c.attrelid=b.oid AND c.attname='val') SELECT t.spcname AS storage_engine FROM pg_tablespace t, pg_class r, tmp m WHERE r.relname = m.tblname AND t.oid=r.reltablespace;

    期待される出力:

    storage_engine
    ----------------
     oss
    (1 row)
ALTER COLUMN を実行した後に挿入されたデータのみが OSS に保存されます。すでに使用中のテーブルから既存の LOB データを移動するには、まず ALTER COLUMN を実行してストレージの場所を設定し、次に VACUUM FULL を実行して既存のすべてのデータを OSS に再書き込みします。VACUUM FULL は実行中の CRUD 操作には影響しませんが、実行中はテーブルをロックするため、大規模なテーブルでは時間がかかることがあります。

時空間分析のストレージコストの削減

このパターンは、統計分析は必要ですがリアルタイムのクエリパフォーマンスは不要な、リモートセンシングや地理空間ワークロードに適用されます。この例では、衛星リモートセンシング画像 (ラスターデータ) を使用し、画像ブロックデータを OSS に移動した際のストレージコストと正規化植生指標 (NDVI) 計算時間のトレードオフを測定します。

この例では、GanosBase の高度な機能を使用します。中間ステップをスキップしたい場合は、最終的な比較結果にご注目ください。

リモートセンシング画像のインポートと分析

  1. 4 つの Landsat リモートセンシング画像を準備します。

    image

  2. 画像をデータベースにインポートします:

    1. rastdb という名前のテストデータベースを作成します。

    2. ganos_raster 拡張機能を作成します。詳細については、「GanosBase Raster」をご参照ください:

      CREATE EXTENSION ganos_raster CASCADE;
    3. 画像をインポートします:

      CREATE TABLE raster_table (id integer, rast raster);
      INSERT INTO raster_table VALUES (1, ST_ImportFrom('rbt','/home/postgres/LC08_L1TP_113028_20190912_20190917_01_T1.TIF'));
      INSERT INTO raster_table VALUES (2, ST_ImportFrom('rbt','/home/postgres/LC08_L1TP_113029_20191030_20191114_01_T1.TIF'));
      INSERT INTO raster_table VALUES (3, ST_ImportFrom('rbt','/home/postgres/LC08_L1TP_114028_20191005_20191018_01_T1.TIF'));
      INSERT INTO raster_table VALUES (4, ST_ImportFrom('rbt','/home/postgres/LC08_L1TP_114029_20200905_20200917_01_T1.TIF'));
  3. 画像ブロックデータが使用するディスク領域を計算します。GanosBase では、ラスターメタデータとブロックデータは別々に保存されます。ブロックテーブルのサイズを合計するストアドプロシージャを作成します:

    CREATE OR REPLACE FUNCTION raster_data_internal_total_size( rast_table_name text, rast_column_name text)
      RETURNS int8 AS $$
    DECLARE
        sql                 text;
        sql2                text;
        rec                 record;
        size                int8;
        totalsize           int8;
        tbloid              Oid;
    BEGIN
        size := 0;
        totalsize := 0;
    
        -- Query the block data table of the raster object
        sql = format('select distinct(st_datalocation(%s)) as tblname from %s where st_rastermode(%s) = ''INTERNAL'';', rast_column_name, rast_table_name, rast_column_name);
        for rec in
            execute sql
        loop
            sql2 = format('select a.oid from pg_class a, pg_tablespace b where a.reltablespace = b.oid and b.spcname=''oss'' and a.relname=''%s'';', rec.tblname);
            execute sql2 into tbloid;
    
            if (tbloid > 0) then
                size := 0;
            else
                -- Calculate the size of each data table
                sql2 = format('select pg_total_relation_size(''%s'');',rec.tblname);
                execute sql2 into size;
            end if;
            totalsize := (totalsize + size);
        end loop;
        return totalsize;
    END;
    $$ LANGUAGE plpgsql;

    計算を実行します:

    SELECT pg_size_pretty(raster_data_internal_total_size('raster_table','rast'));

    画像は約 1.2 GB のデータベースストレージを占有します:

    pg_size_pretty
    ----------------
     1319 MB
    (1 row)
  4. ディスク上のデータで NDVI を計算します。NDVI 分析の前に、モザイク操作で画像を結合します。ST_MosaicFrom の詳細については、「ST_MosaicFrom」をご参照ください:

    CREATE TABLE rast_mapalgebra_result(id integer, rast raster);
    
    INSERT INTO rast_mapalgebra_result SELECT 1, ST_MapAlgebra(ARRAY(SELECT st_mosaicfrom(ARRAY(SELECT rast FROM raster_table ORDER BY id), 'rbt_mosaic','','{"srid":4326,"cell_size":[0.005,0.005]')),    '[{"expr":"([0,3] - [0,2])/([0,3] + [0,2])","nodata": true, "nodataValue":0}]',    '{"chunktable":"rbt_algebra","celltype":"32bf"}');
    INSERT 0 1
    Time: 39874.189 ms (00:39.874)
  5. ブロックデータを OSS にアーカイブします。メタデータをディスク上に保持したまま、ブロックデータテーブルを OSS に移動するストアドプロシージャを作成します:

    CREATE OR REPLACE FUNCTION raster_data_alter_to_oss( rast_table_name text, rast_column_name text)
      RETURNS VOID AS $$
    DECLARE
        sql                 text;
        sql2                text;
        rec                 record;
    BEGIN
        -- Query the data table of the raster object
        sql = format('select distinct(st_datalocation(%s)) as tblname from %s where st_rastermode(%s) = ''INTERNAL'';', rast_column_name, rast_table_name, rast_column_name);
        for rec in
            execute sql
        loop
            sql2 = format('alter table %s set tablespace oss;',rec.tblname);
            execute sql2;
        end loop;
    END;
    $$ LANGUAGE plpgsql;

    ブロックデータをアーカイブし、結果を確認します:

    SELECT raster_data_alter_to_oss('raster_table', 'rast');
    
    -- ディスク使用率が 0 になったことを確認します
    SELECT pg_size_pretty(raster_data_internal_total_size('raster_table','rast'));
    pg_size_pretty
    ----------------
     0 bytes
    (1 row)

    ブロックデータは OSS に格納されるようになりました。

  6. OSS のブロックデータで NDVI を再計算します:

    INSERT INTO rast_mapalgebra_result select 2, ST_MapAlgebra(ARRAY(select st_mosaicfrom(ARRAY(SELECT rast FROM raster_table ORDER BY id), 'rbt_mosaic','','{"srid":4326,"cell_size":[0.005,0.005]')),    '[{"expr":"([0,3] - [0,2])/([0,3] + [0,2])","nodata": true, "nodataValue":0}]',    '{"chunktable":"rbt_algebra","celltype":"32bf"}');
    INSERT 0 1
    Time: 69414.201 ms (01:09.414)

    image

ストレージコストとパフォーマンスの比較

ディスクOSS比率
ストレージコスト1,319 MB (0.238 USD/GB/月) = 0.31 USD

1011.834 MB (0.0232 USD/GB/月) = 0.023 USD

1,011.834 MB (0.0232 USD/GB/月) = 0.023 USD10:1
NDVI 計算時間39 秒69 秒1:1.76

OSS のストレージコストは、ディスクストレージコストの 10 分の 1 未満です。パフォーマンスのオーバーヘッドは 100% 未満 (2 倍未満) であり、これは非リアルタイムの統計分析には許容範囲です。

次のステップ