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

Hologres:Fixed Plan を使用した SQL 実行の高速化

最終更新日:Jan 16, 2026

Fixed Plan は、Hologres 実行エンジン独自の最適化メソッドです。このトピックでは、SQL ステートメントで Fixed Plan を使用するために必要な条件とパラメーター設定について説明します。

背景情報

Fixed Plan は、Hologres 実行エンジン独自の最適化メソッドです。従来の SQL 実行は、オプティマイザー、コーディネーター、クエリエジン、ストレージエンジンなど、複数のコンポーネントを通過します。Fixed Plan はショートカットパスを使用して SQL 実行を最適化し、オプティマイザー、コーディネーター、およびクエリエジンの一部のオーバーヘッドをバイパスします。Fixed Frontend は Fixed Query Engine に直接接続します。これにより、SQL 実行効率が大幅に向上し、高スループットのリアルタイム書き込みや高同時実行性クエリにとって重要な最適化となります。Fixed Plan の詳細については、「サービスアーキテクチャ」をご参照ください。

Hologres では、以下のシナリオでデフォルトで Fixed Plan が使用されます。

  • Flink から Hologres へのリアルタイムデータ書き込み。

  • DataWorks のデータ統合から Hologres へのリアルタイムデータ書き込み。

  • Holo Client を使用した Hologres へのデータ書き込み。

その他の書き込みシナリオでは、Fixed Plan を使用するように SQL ステートメントを設定する必要があります。詳細については、以降のセクションをご参照ください。

説明

これらのシナリオでは SQL ステートメントはデフォルトで Fixed Plan を使用しますが、すべてのステートメントが必要な条件を満たすわけではありません。

関連 GUC パラメーター

  • GUC リスト

    以下の Grand Unified Configuration (GUC) パラメーターは Fixed Plan で使用されます。各パラメーターの値は on または off に設定できます。すべてのパラメーターは Holo Client でデフォルトで有効になっており、セッションレベルで有効になります。

    GUC 名

    シナリオ

    デフォルト値

    GUC 変更履歴

    hg_experimental_enable_fixed_dispatcher

    インスタンスで Fixed Plan が有効になっているかどうかを確認します。

    データの書き込み、更新、削除、クエリを行うための単一行の INSERT、UPDATE、DELETE、および PrefixScan 操作の Fixed Plan をサポートします。

    on

    該当なし。

    hg_experimental_enable_fixed_dispatcher_for_multi_values

    複数行の INSERT 操作に対する Fixed Plan の書き込みを制御します。

    説明

    原子性は保証されません。一度に複数のレコードを書き込む際に、エラーが報告されなければ、すべてのレコードが正常に書き込まれます。1 つのレコードでエラーが報告された場合、すべてのレコードの書き込みが失敗したか、一部が書き込まれて一部が書き込まれなかった可能性があります。失敗したレコードのエラーは、リトライのためにクライアントアプリケーションに送信されます。

    on

    Hologres V1.3.35 以降、この GUC は複数行の Insert、Update、Delete 操作の Fixed Plan をサポートします。

    hg_experimental_enable_fixed_dispatcher_autofill_series

    Serial 型の列を含むテーブルへの Fixed Plan 書き込みをサポートします。クライアント側でセッションレベルでこのパラメーターを有効にすることを推奨します。

    off

    Hologres V1.3.25 以降、この GUC パラメーターのデフォルト値は on です。

    hg_experimental_enable_fixed_dispatcher_for_update

    UPDATE 操作の Fixed Plan をサポートします。クライアント側でセッションレベルでこのパラメーターを有効にすることを推奨します。

    off

    Hologres V1.3.25 以降、hg_experimental_enable_fixed_dispatcher_for_update パラメーターは非推奨になりました。条件を満たす UPDATE ステートメントは、デフォルトで Fixed Plan を使用します。複数行を更新するには、set hg_experimental_enable_fixed_dispatcher_for_multi_values =on を設定する必要があります。

    hg_experimental_enable_fixed_dispatcher_for_delete

    DELETE 操作の Fixed Plan をサポートします。クライアント側でセッションレベルでこのパラメーターを有効にすることを推奨します。

    off

    Hologres V1.3.25 以降、hg_experimental_enable_fixed_dispatcher_for_delete パラメーターは非推奨になりました。条件を満たす DELETE ステートメントは、デフォルトで Fixed Plan を使用します。複数行を削除するには、set hg_experimental_enable_fixed_dispatcher_for_multi_values =on を設定する必要があります。

    hg_experimental_enable_fixed_dispatcher_for_scan

    PrefixScan クエリの Fixed Plan をサポートします。

    説明

    PrefixScan クエリは、複数列のプライマリキーの最初の数カラムのみをフィルター条件として使用します。列指向テーブルでの PrefixScan に対する Fixed Plan クエリはサポートされていません。

    off

    バージョン 1.3.35 以降でこのパラメーターを使用することを推奨します。

    hg_experimental_enable_bhclient_cache_on_session

    キャッシュモードを変更します。2 つのモードが利用可能です。

    • on: cached on session モードを使用します。

    • off: cached on fe モードを使用します。

    説明

    cached on session モードと cached on fe モードの違いは以下の通りです。

    • cached on session モードでは、各接続が独自の Writer と Reader を持ちます。このモードは単一接続のスループットが高いですが、起動が遅くなります。各テーブルでの最初の読み取りまたは書き込み操作には起動時間が必要です。

    • cached on fe モードでは、フロントエンド (FE) ノード上のすべての接続が Writer と Reader を共有します。接続が閉じられても Writer と Reader はシャットダウンしません。これにより、起動時間が不要になります。

    off

    該当なし。

    hg_experimental_disable_fixed_planner_conflict_pk_check

    INSERT INTO <table_name> VALUES (...) ON CONFLICT(<column>) 構文の列が非プライマリキーフィールドであることができるかどうかを制御します。

    • false: いいえ。

    • true: この機能はサポートされています。

      説明

      この GUC パラメーターが true に設定されている場合、列は非プライマリキーフィールドにすることができます。ただし、INSERT ON CONFLICT ステートメントは、プライマリキーが重複しているかどうかに基づいて実行されます (ON CONFLICT(pk))。

    false

    • Hologres V1.3 から V2.1.28 まで、ON CONFLICT(<column>) のフィールドはプライマリキーフィールドでなければなりません。

    • Hologres V2.1.29 以降、この GUC パラメーターは ON CONFLICT(<column>) のフィールドが非プライマリキーフィールドであることができるかどうかを制御します。

  • GUC の使用

    • GUC が有効かどうかの確認

      `SHOW` コマンドを実行して、GUC が有効かどうかを確認できます。

      SHOW <GUC_name>;

      以下にコマンドの使用例を示します。

      -- インスタンスレベルで Fixed Plan が有効になっているか確認します。
      SHOW hg_experimental_enable_fixed_dispatcher;
    • GUC の有効化

      • セッションレベルで Grand Unified Configuration (GUC) パラメーターを有効にする

        set コマンドを使用して、セッションレベルで GUC パラメーターを設定できます。セッションレベルのパラメーターは現在のセッションでのみ有効です。セッションが閉じられると設定は無効になります。SQL ステートメントの前にコマンドを追加し、一緒に実行することを推奨します。構文は以下の通りです。

        SET <GUC_name> = <values>;

        GUC_name は GUC パラメーターの名前を指定し、values は GUC パラメーターの値を指定します。

        以下に例を示します。

        -- 複数行の insert on conflict レコードに対して Fixed Plan の書き込みを許可します。
        SET hg_experimental_enable_fixed_dispatcher_for_multi_values = on;
      • データベースレベルで GUC パラメーターを有効にする

        alter database xx set xxx コマンドを使用して、データベースレベルで GUC パラメーターを設定できます。この設定は、コマンド実行後にデータベース全体に適用されます。設定を有効にするには、データベースに再接続する必要があります。この設定は新しいデータベースには適用されません。新しいデータベースには再度手動でパラメーターを設定する必要があります。構文は以下の通りです。

        ALTER DATABASE <db_name> SET <GUC_name> = <values>;

        db_name はデータベース名を指定し、GUC_name は GUC パラメーターの名前を指定し、values は GUC パラメーターの値を指定します。

        以下に例を示します。

        --DB レベルで Fixed Plan を有効にします。
        ALTER DATABASE <db_name> SET hg_experimental_enable_fixed_dispatcher = on;

データ型の要件

  • テーブル内のどの列も MONEY または MONEY ARRAY 型であってはなりません。

  • INSERT、UPDATE、DELETE などのデータ操作言語 (DML) 操作を実行する列、および SELECT ステートメントの列では、以下のデータ型がサポートされています。SELECT ステートメントのターゲット列と `where` 句の列は、要件を満たす必要があります。

    • BOOLEAN (エイリアス:BOOL)

    • SMALLINT

    • INTEGER (エイリアス:INT または INT4)

    • BIGINT (エイリアス:INT8)

    • FLOAT (エイリアス:FLOAT4)

    • DOUBLE PRECISION (エイリアス:FLOAT8)

    • CHAR(n)

    • VARCHAR(n)

    • BYTEA

    • JSON および JSONB

    • TEXT (エイリアス:VARCHAR)

    • TIMESTAMP WITH TIME ZONE (エイリアス:TIMESTAMPTZ)

    • DATE

    • TIMESTAMP

    • DECIMAL (エイリアス:NUMERIC)

    • ROARINGBITMAP

    • TIME (Hologres V2.2 以降でサポート)

    • TIMETZ (Hologres V2.2 以降でサポート)

    • 配列型

      • boolean[]

      • smallint[]

      • int4[]

      • int8[]

      • float4[]

      • float8[]

      • char(n)[]

      • varchar(n)[]

      • text[]

INSERT シナリオ

Hologres V3.2 以降、プライマリキーを持つテーブルで `INSERT` ステートメントを実行する際に、Fixed Plan を使用して `RETURNING` 句がサポートされます。

  • INSERT ステートメント

    Fixed Plan は以下の INSERT 句をサポートします。

    -- 単一行を書き込みます。
    INSERT INTO TABLE(col1,col2,col3..) VALUES(?,?,?..) ON conflict xxx;
    -- 複数行を書き込みます。
    INSERT INTO TABLE(col1,col2,col3..) VALUES(?,?,?..),(?,?,?..) ON conflict xxx;
    説明
    • INSERT コマンドは内部テーブルにデータを書き込みますが、外部テーブルには書き込みません。

    • Hologres は INSERT コマンドを使用したパーティションテーブルへの書き込みをサポートしています。Hologres V1.3 以降では、親パーティションテーブルにも書き込むことができます。

    • Fixed Plan は INSERT ステートメントの RETURNING キーワードをサポートしていません。

  • 単一行の INSERT ON CONFLICT

    • 以下のシナリオがサポートされています。

      • ON CONFLICT のない句がサポートされています。

      • ON CONFLICT DO NOTHING のある句がサポートされています。

      • ON CONFLICT DO UPDATE のある句がサポートされています。INSERT ステートメントの一部であるすべての非プライマリキー (PK) 列を更新する必要があります。PK 列を更新するかどうかは選択できます。更新は col = excluded.col 形式を使用する必要があります。Hologres V1.3 以降では、一部の非 PK 列を更新できますが、それでも col = excluded.col 形式を使用する必要があります。

    • 以下にステートメントの使用例を示します。

      BEGIN;
      CREATE TABLE test_insert_oneline (
          pk1 INT,
          pk2 INT,
          col1 INT,
          col2 INT,
          PRIMARY KEY (pk1, pk2)
      );
      COMMIT;
      
      --すべての非 PK 列を更新します。Fixed Plan を使用できます。
      INSERT INTO test_insert_oneline
          VALUES (1, 2, 3, 4)
      ON CONFLICT (pk1, pk2)
          DO UPDATE SET
              col1 = excluded.col1, col2 = excluded.col2;
      
      --すべての列 (PK と非 PK 列を含む) を更新します。Fixed Plan を使用できます。
      INSERT INTO test_insert_oneline
          VALUES (1, 2, 3, 4)
      ON CONFLICT (pk1, pk2)
          DO UPDATE SET
              col1 = excluded.col1, col2 = excluded.col2, pk1 = excluded.pk1, pk2 = excluded.pk2;
      
      --挿入するすべての非 PK 列を更新する必要があります。この例には col2 は含まれていません。Fixed Plan は Hologres V1.3 以降でのみサポートされます。
      INSERT INTO test_insert_oneline
          VALUES (1, 2, 3, 4)
      ON CONFLICT (pk1, pk2)
          DO UPDATE SET
              col1 = excluded.col1;
      
      --更新は `set col = excluded.col` 形式である必要があります。そのため、Fixed Plan は使用できません。
      INSERT INTO test_insert_oneline
          VALUES (1, 2, 3, 4)
      ON CONFLICT (pk1, pk2)
          DO UPDATE SET
              col1 = excluded.col1, col2 = 5;
  • 複数行の INSERT ON CONFLICT

    • 複数行の INSERT ON CONFLICT の句は以下の通りです。

      SET hg_experimental_enable_fixed_dispatcher_for_multi_values = ON;
      
      INSERT INTO TABLE (col1, col2, col3..)
          VALUES (?, ?, ?..), (?, ?, ?..)
      ON CONFLICT xxx;
      • GUC パラメーターを設定する必要があります: hg_experimental_enable_fixed_dispatcher_for_multi_values = on;。このパラメーターは Hologres 1.3.35 以降ではデフォルトで on です。

      • 原子性は保証されません。一度に複数の行を書き込む際にエラーが報告されなければ、すべての行が正常に書き込まれます。エラーが報告された場合、すべての行の書き込みが失敗したか、一部が書き込まれて一部が書き込まれなかった可能性があります。

    • 複数行を書き込む別の方法は以下の通りです。

      SET hg_experimental_enable_fixed_dispatcher_for_multi_values = ON;
      
      INSERT INTO TABLE selectunnest (ARRAY[TRUE, FALSE, TRUE]::bool[]), unnest(ARRAY[1, 2, 3]::int4[]), unnest(ARRAY[1.11, 2.222, 3]::float4[])
      ON CONFLICT xxx;
      
      • GUC パラメーターを設定する必要があります: hg_experimental_enable_fixed_dispatcher_for_multi_values=on;

      • 書き込む列は配列型であってはなりません。

      • `unnest` の ARRAY は、対応する列の配列型に明示的にキャストする必要があります。

      以下に例を示します。

      BEGIN;
      CREATE TABLE test_insert_multiline (
          pk1 int8,
          col1 float4,
          PRIMARY KEY (pk1)
      );
      COMMIT;
      
      --Fixed Plan がサポートされています。
      SET hg_experimental_enable_fixed_dispatcher_for_multi_values = ON;
      
      INSERT INTO test_insert_multiline
      SELECT
          unnest(ARRAY[1, 2, 3]::int8[]),
          unnest(ARRAY[1.11, 2.222, 3]::float4[])
      ON CONFLICT
          DO NOTHING;
      
      --unnest の ARRAY が明示的にキャストされていません。Fixed Plan はサポートされていません。
      INSERT INTO test_insert_multiline
      SELECT
          unnest(ARRAY[1, 2, 3]),
          unnest(ARRAY[1.11, 2.222, 3])
      ON CONFLICT
          DO NOTHING;
      
      --最初の列は int8 なので、int8[] にキャストする必要があります。この例では int4[] を使用しています。そのため、Fixed Plan はサポートされていません。
      INSERT INTO test_insert_multiline
      SELECT
          unnest(ARRAY[1, 2, 3]::int4[]),
          unnest(ARRAY[1.11, 2.222, 3]::float4[])
      ON CONFLICT
          DO NOTHING;
  • 部分更新シナリオ

    Hologres では、プライマリキーに基づいてテーブルの一部の列を更新できます。以下の条件が満たされれば、Fixed Plan も部分更新をサポートします。

    • INSERT ステートメントの列は、数と順序において UPDATE ステートメントの列と一致する必要があります。

    • 更新は col = excluded.col 形式を使用する必要があります。

  • 条件付きチェックを伴う Upsert

    同じ PK を持つ行の順不同の入力データを処理し、HBase の CheckAndPut に似たインターフェイスをサポートするために、Hologres は以下の条件が満たされた場合に、条件付きチェックを伴う INSERT または UPDATE ステートメントで Fixed Plan を使用できます。

    • これは単一行のデータを挿入する場合にサポートされます。複数行のデータを挿入するには、GUC パラメーターを設定する必要があります: set hg_experimental_enable_fixed_dispatcher_for_multi_values=on;

    • WHERE 句には単一の非 PK フィールドのみを含めることができます。比較演算子は =, <>, >, >=, <, <=, IS NULL, IS NOT NULL のいずれかでなければなりません。この非 PK フィールドで coalesce 関数を使用できます。

    以下にステートメントの使用例を示します。

    BEGIN;
    CREATE TABLE test_check_and_insert (
        pk INT,
        col INT,
        scn INT,
        PRIMARY KEY (pk)
    );
    COMMIT;
    
    --Fixed Plan がサポートされています。
    --列の既存の値を定数と比較します。
    INSERT INTO test_check_and_insert AS old
        VALUES (1, 1, 1)
    ON CONFLICT (pk)
        DO UPDATE SET
            col = excluded.col, scn = excluded.scn
        WHERE
            old.scn > 0;
    
    --列の既存の値を書き込む値と比較します。
    INSERT INTO test_check_and_insert AS old
        VALUES (1, 1, 1)
    ON CONFLICT (pk)
        DO UPDATE SET
            col = excluded.col, scn = excluded.scn
        WHERE
            old.scn > excluded.scn;
    
    --既存の値が null の可能性がある場合は、coalesce を使用します。
    INSERT INTO test_check_and_insert AS old
        VALUES (1, 1, 1)
    ON CONFLICT (pk)
        DO UPDATE SET
            col = excluded.col, scn = excluded.scn
        WHERE
            coalesce(old.scn, 3) > 2;
    
    INSERT INTO test_check_and_insert AS old
        VALUES (1, 1, 1)
    ON CONFLICT (pk)
        DO UPDATE SET
            col = excluded.col, scn = excluded.scn
        WHERE
            coalesce(old.scn, 3) > excluded.scn;
    
    --Fixed Plan がサポートされています。
    SET hg_experimental_enable_fixed_dispatcher_for_multi_values = ON;
    
    --列の既存の値を定数と比較します。
    INSERT INTO test_check_and_insert AS old
        VALUES (1, 1, 1), (2, 3, 4)
    ON CONFLICT (pk)
        DO UPDATE SET
            col = excluded.col, scn = excluded.scn
        WHERE
            old.scn > 3;
    
    --unnest 構文もサポートされています。
    INSERT INTO test_check_and_insert AS old
    SELECT
        unnest(ARRAY[5, 6, 7]::int[]),
        unnest(ARRAY[1, 1, 1]::int[]),
        unnest(ARRAY[1, 1, 1]::int[])
    ON CONFLICT (pk)
        DO UPDATE SET
            col = excluded.col,
            scn = excluded.scn
        WHERE
            old.scn > 3;
  • デフォルト列

    デフォルト値を持つ列を含むテーブルで Fixed Plan を使用するには、以下の条件を満たす必要があります。

    • これは単一行のデータを挿入する場合にサポートされます。複数行のデータを挿入するには、Hologres インスタンスが V1.1.36 以降である必要があります。インスタンスがそれ以前のバージョンの場合は、アップグレードする必要があります。また、GUC パラメーターを設定する必要があります: set hg_experimental_enable_fixed_dispatcher_for_multi_values=on;

    • Hologres V1.3 以降のバージョンは、DEFAULT 列を持つテーブルでの Insert on conflict 句の Fixed Plan をサポートします。以前のバージョンでは、DEFAULT 列を持つテーブルでの Insert on conflict 句の Fixed Plan はサポートされていません。

    以下に例を示します。

    BEGIN;
    CREATE TABLE test_insert_default (
        pk1 INT,
        col1 INT DEFAULT 99,
        PRIMARY KEY (pk1)
    );
    COMMIT;
    
    --Fixed Plan がサポートされています。
    INSERT INTO test_insert_default (pk1)
        VALUES (1);
    
    --V1.1.36 以降でサポートされています。
    SET hg_experimental_enable_fixed_dispatcher_for_multi_values = ON;
    
    INSERT INTO test_insert_default (pk1)
        VALUES (1), (2), (3);
  • SERIAL 列を持つテーブル

    自動インクリメントの SERIAL 列を持つテーブルへの単一行または複数行の書き込みに Fixed Plan を使用するには、以下の条件を満たす必要があります。

    • GUC パラメーターを設定する必要があります: set hg_experimental_enable_fixed_dispatcher_autofill_series=on;。Hologres V1.3.25 以降、この GUC パラメーターはデフォルトで on です。

    • 複数行のデータを挿入するには、GUC パラメーターも設定する必要があります: set hg_experimental_enable_fixed_dispatcher_for_multi_values=on;

    以下に例を示します。

    BEGIN;
    CREATE TABLE test_insert_serial (
        pk1 INT,
        col1 SERIAL,
        PRIMARY KEY (pk1)
    );
    COMMIT;
    
    --Fixed Plan がサポートされています。
    SET hg_experimental_enable_fixed_dispatcher_autofill_series = ON;
    
    INSERT INTO test_insert_serial (pk1)
        VALUES (1);
    
    --Fixed Plan がサポートされています。
    SET hg_experimental_enable_fixed_dispatcher_autofill_series = ON;
    
    SET hg_experimental_enable_fixed_dispatcher_for_multi_values = ON;
    
    INSERT INTO test_insert_serial (pk1)
        VALUES (1), (2), (3);

UPDATE シナリオ

  • UPDATE ステートメント

    以下の UPDATE 句は Fixed Plan を使用できます。

    SET hg_experimental_enable_fixed_dispatcher_for_update = ON;
    
    UPDATE TABLE SET col1 = ?,col2 = ? WHERE pk1 = ? AND pk2 = ?;
  • UPDATE シナリオ

    UPDATE シナリオで Fixed Plan を使用するには、以下の条件を満たす必要があります。

    • 内部テーブルは更新できますが、外部テーブルは更新できません。子パーティションテーブルは更新できますが、親パーティションテーブルは更新できません。テーブルにはプライマリキー (PK) が必要です。

    • GUC パラメーターを設定する必要があります: hg_experimental_enable_fixed_dispatcher_for_update=on;。Hologres V1.3.25 以降、このパラメーターは非推奨です。条件を満たす UPDATE ステートメントは、デフォルトで Fixed Plan を使用します。複数行を更新するには、GUC パラメーターを設定する必要があります: set hg_experimental_enable_fixed_dispatcher_for_multi_values =on

    • SET 句の列はプライマリキー (PK) であってはなりません。

    • `WHERE` 句には、すべての PK のみを含める必要があります。

    • pk IN (?,?,?) または pk = ANY() を使用して、一度に複数の行を変更できます。たとえば、pk1 IN (1,2) and pk2 = ANY('{3,4}') and pk3 = 5 は 4 つの行 (1,3,5), (1,4,5), (2,3,5), and (2,4,5) を変更します。

    • `WHERE` 句の各列には 1 つの条件しか持てません。同一の条件は 1 つとして扱われます。

    以下に例を示します。

    BEGIN;
    CREATE TABLE test_update (
        pk1 INT,
        pk2 INT,
        col1 INT,
        col2 INT,
        PRIMARY KEY (pk1, pk2)
    );
    COMMIT;
    
    --Fixed Plan がサポートされています。
    SET hg_experimental_enable_fixed_dispatcher_for_update = ON;
    
    UPDATE
        test_update
    SET
        col1 = 1,
        col2 = 2
    WHERE
        pk1 = 3
        AND pk2 = 4;
    
    --Fixed Plan がサポートされています。
    SET hg_experimental_enable_fixed_dispatcher_for_update = ON;
    
    UPDATE
        test_update
    SET
        col1 = 1
    WHERE
        pk1 = 3
        AND pk2 = 4;
    
    --Fixed Plan がサポートされています。
    SET hg_experimental_enable_fixed_dispatcher_for_update = ON;
    
    UPDATE
        test_update
    SET
        col1 = 1,
        col2 = 2
    WHERE
        pk1 IN (1, 2)
        AND pk2 = ANY ('{3,4}');
    
    --pk1 には複数のフィルター条件があります。Fixed Plan はサポートされていません。
    UPDATE
        test_update
    SET
        col1 = 1,
        col2 = 2
    WHERE
        pk1 = 3
        AND pk1 = 4;
    
    --pk1 には複数のフィルター条件があります。Fixed Plan はサポートされていません。
    UPDATE
        test_update
    SET
        col1 = 1,
        col2 = 2
    WHERE
        pk1 IN (1, 2)
        AND pk1 = 1;
    
    --pk1 には複数のフィルター条件がありますが、条件は同一です。Fixed Plan はサポートされています。
    SET hg_experimental_enable_fixed_dispatcher_for_update = ON;
    
    UPDATE
        test_update
    SET
        col1 = 1,
        col2 = 2
    WHERE
        pk1 IN (1, 2)
        AND pk1 IN (1, 2)
        AND pk2 = 4;

DELETE シナリオ

  • DELETE ステートメント

    以下の DELETE 句は Fixed Plan を使用できます。

    SET hg_experimental_enable_fixed_dispatcher_for_delete = ON;
    
    DELETE FROM TABLE
    WHERE pk1 = ?
        AND pk2 = ?
        AND pk3 = ?;
  • DELETE シナリオ

    DELETE シナリオで Fixed Plan を使用するには、以下の条件を満たす必要があります。

    • 内部テーブルからは削除できますが、外部テーブルからは削除できません。子パーティションテーブルからは削除できますが、親パーティションテーブルからは削除できません。テーブルにはプライマリキー (PK) が必要です。

    • GUC パラメーターを設定する必要があります: hg_experimental_enable_fixed_dispatcher_for_delete=on;。Hologres V1.3.25 以降、このパラメーターは非推奨です。DELETE ステートメントが条件を満たす場合、デフォルトで Fixed Plan を使用します。複数行を削除するには、GUC パラメーターを設定する必要があります: set hg_experimental_enable_fixed_dispatcher_for_multi_values =on

    • WHERE 句には、すべての PK のみを含める必要があります。Hologres V1.3 以降、WHERE フィルター条件の最後のフィールドは非 PK フィールドにすることができます。この非 PK フィールドは、=, <>, >, >=, <, <=, IS NULL, and IS NOT NULL 比較演算子と coalesce 関数をサポートします。

    • pk IN (?,?,?) または pk = ANY() を使用して、一度に複数の行を削除できます。たとえば、pk1 IN (1,2) and pk2 = ANY('{3,4}') and pk3 = 5 は 4 つの行 (1,3,5), (1,4,5), (2,3,5), and (2,4,5) を削除します。

    • 各列には 1 つの条件しか持てません。同一の条件は 1 つとして扱われます。

    以下に例を示します。

    BEGIN;
    CREATE TABLE test_delete (
        pk1 INT,
        pk2 INT,
        col1 INT,
        col2 INT,
        PRIMARY KEY (pk1, pk2)
    );
    COMMIT;
    
    --Fixed Plan がサポートされています。その他のシナリオは UPDATE の例と一致します。
    SET hg_experimental_enable_fixed_dispatcher_for_delete = ON;
    
    DELETE FROM test_delete
    WHERE pk1 = 1
        AND pk2 = 2;
    

SELECT シナリオ

  • SELECT ステートメント

    以下の SELECT 句は Fixed Plan を使用できます。

    SELECT
        col1,
        col2,
        col3,
    ...
    FROM
        TABLE
    WHERE
        pk1 = ?
        AND pk2 = ?
        AND pk3 = ?;
    
    • 内部テーブルからは選択できますが、外部テーブルからは選択できません。

    • 子パーティションテーブルからは選択できますが、親パーティションテーブルからは選択できません。

    • テーブルにはプライマリキー (PK) が必要です。

  • ポイントクエリ (キー・バリュー) シナリオ

    ポイントクエリシナリオには以下の条件が適用されます。

    • `WHERE` 句には、すべての PK のみを含める必要があります。

    • pk IN (?,?,?) または pk = ANY() を使用して、一度に複数の行をクエリできます。たとえば、 pk1 IN (1,2) and pk2 = ANY('{3,4}') and pk3 = 5 は 4 つの行 (1,3,5), (1,4,5), (2,3,5), and (2,4,5) をクエリします。

    • 各列には 1 つの条件しか持てません。同一の条件は 1 つとして扱われます。

    • LIMIT 句が使用される場合、その値は 0 より大きくなければなりません。

    以下に例を示します。

    BEGIN;
    CREATE TABLE test_select (
        pk1 INT,
        pk2 INT,
        col1 INT,
        col2 INT,
        PRIMARY KEY (pk1, pk2)
    );
    CALL set_table_property ('test_select', 'orientation', 'row');
    COMMIT;
    
    --Fixed Plan がサポートされています。
    SELECT * FROM test_select WHERE pk1 = 1 AND pk2 = 2;
  • PrefixScan シナリオ

    • PrefixScan シナリオ句

      PrefixScan シナリオは、テーブルに複数のプライマリキーがあり、クエリが左一致の原則に基づいて最初のいくつかのプライマリキーのみを使用する場合に発生します。クエリ句は以下の通りです。

      SET hg_experimental_enable_fixed_dispatcher_for_scan = on;
      SELECT col1,col2,col3,... FROM TABLE WHERE pk1 = ? AND pk2 = ?;
      SELECT col1,col2,col3,... FROM TABLE WHERE pk1 = ? AND pk2 < ?;--V1.1.48 以降、最後の PK 列は範囲条件を持つことができます。
      SELECT col1,col2,col3,... FROM TABLE WHERE pk1 = ? AND pk2 BETWEEN ? AND ?;--V1.1.48 以降、最後の PK 列は範囲条件を持つことができます。                                
    • PrefixScan の使用

      PrefixScan を使用するには、以下の条件を満たす必要があります。

      • GUC パラメーターを設定する必要があります: hg_experimental_enable_fixed_dispatcher_for_scan=on;。Hologres インスタンスは V1.3.35 以降である必要があります。

      • テーブルには Distribution Key が必要で、WHERE 句にはすべての Distribution Key を含める必要があります。

      • WHERE 句には PK のプレフィックスのみを含める必要があります。V1.1.48 以降、PrefixScan は最後のプライマリキー列に上限と下限を含む範囲を設定することをサポートします。

        説明

        プレフィックスの定義: PK が (pk1,pk2,pk3) の場合、プレフィックスは (pk1),(pk1,pk2) です。

      • 行指向テーブル (行列表ハイブリッドテーブルを含む) のみが PrefixScan をサポートします。

      • 各列には 1 つの条件しか持てません。同一の条件は 1 つとして扱われます。

      • `LIMIT` 句が使用される場合、その値は 0 より大きくなければなりません。

      説明

      PrefixScan はすべての結果行を一度に返します。結果のバイトサイズが hg_experimental_fixed_scan_bytesize_limit より大きい場合、"scan result size larger than fixed scan size limit" というエラーが報告されます。hg_experimental_fixed_scan_bytesize_limit パラメーターをシナリオに合わせて設定できます。デフォルト値は 1,048,576 バイト (1 MB) です。

      たとえば、テーブルの PK が (pk1,pk2,pk3,pk4) で、Distribution Key が pk1,pk3 の場合。

      BEGIN;
      CREATE TABLE test_select_prefix (
          pk1 INT,
          pk2 INT,
          pk3 INT,
          pk4 INT,
          PRIMARY KEY (pk1, pk2, pk3, pk4)
      );
      CALL set_table_property ('test_select_prefix', 'orientation', 'row');
      CALL set_table_property ('test_select_prefix', 'distribution_key', 'pk1,pk3');
      COMMIT;
      
      --すべての distribution key が含まれていません。Fixed Plan は使用できません。
      SELECT * FROM test_select_prefix WHERE pk1 = ? AND pk2 = ?;
      --これは PK のプレフィックスではありません。Fixed Plan は使用できません。
      SELECT * FROM test_select_prefix WHERE pk1 = ? AND pk3 = ?;
      
      --Fixed Plan を使用できます。
      SET hg_experimental_enable_fixed_dispatcher_for_scan = ON;
      
      SELECT * FROM test_select_prefix WHERE pk1 = ? AND pk2 = ? AND pk3 = ?;
      

      pk IN (?,?,?) または pk = ANY() を使用して、一度に複数の行をクエリできます。コマンドは以下の通りです。

      pk1 IN (1,2) AND pk2 = 3 <=> 2つのグループをスキャンします: (1,3) と (2,3)
      pk2 =any('{3,4}') AND pk1 IN (1,2) <=> 4つのグループをスキャンします: (1,3), (1,4), (2,3), (2,4)
    • 使用例

      BEGIN;
      CREATE TABLE test_scan (
          pk1 INT,
          pk2 INT,
          pk3 INT,
          col1 INT,
          PRIMARY KEY (pk1, pk2, pk3)
      );
      CALL set_table_property ('test_scan', 'orientation', 'row');
      CALL set_table_property ('test_scan', 'distribution_key', 'pk1,pk2');
      COMMIT;
      
      INSERT INTO test_scan
          VALUES (1, 2, 3, 4);
      
      --Fixed Plan がサポートされています。
      SET hg_experimental_enable_fixed_dispatcher_for_scan = ON;
      
      SELECT * FROM test_scan WHERE pk1 = 1 AND pk2 = 2;
      
      --Fixed Plan がサポートされています。
      SET hg_experimental_enable_fixed_dispatcher_for_scan = ON;
      
      SELECT * FROM test_scan WHERE pk1 = 1 AND pk2 IN (2, 3);
      
      --Fixed Plan がサポートされています。
      SET hg_experimental_enable_fixed_dispatcher_for_scan = ON;
      
      SELECT * FROM test_scan WHERE pk1 = ANY ('{3,4}') AND pk2 IN (2, 3);
      
      --Fixed Plan がサポートされています。最後の PK 列には範囲条件があります。V1.1.48 以降でサポートされています。
      SET hg_experimental_enable_fixed_dispatcher_for_scan = ON;
      
      SELECT * FROM test_scan WHERE pk1 = 1 AND pk2 = 1 AND pk3 > 1 AND pk3 < 4;
      
      --Fixed Plan がサポートされています。最後の PK 列には範囲条件があります。V1.1.48 以降でサポートされています。
      SET hg_experimental_enable_fixed_dispatcher_for_scan = ON;
      
      SELECT * FROM test_scan WHERE pk1 = 1 AND pk2 = 1 AND pk3 BETWEEN 1 AND 4;
      
      --すべての distribution key が含まれていません。Fixed Plan はサポートされていません。
      SELECT * FROM test_scan WHERE pk1 = 1;
      
      --プライマリキーのプレフィックスと一致しません。Fixed Plan はサポートされていません。
      SELECT * FROM test_scan WHERE pk2 = 2;
  • ページクエリシナリオ

    Hologres V3.2 以降、Fixed Plan は部分的なプライマリキーに基づく PrefixScan シナリオでのページクエリをサポートします。以下の例でその仕組みを示します:

    説明
    • デフォルトでは、PrefixScan の結果はプライマリキーの昇順で返されます。たとえば、以下の SQL ステートメントでは、`pk1` と `pk2` に基づく PrefixScan は `pk3` の昇順でソートされた結果を返します。

    • カスタムのソート順を指定するには、Clustering Key で対応する列の順序を設定し、クエリ実行時に関連する GUC を指定します。結果は Clustering Key によってソートされます。Clustering Key のフィールドはプライマリキーと同一でなければなりません。たとえば、結果を降順で返すには、Clustering Key の最後の項目を手動で pk3:desc に設定できます。

    • 昇順でのページ分割結果

      -- テーブルを作成します。
      CREATE TABLE test_scan(
        pk1 INT, 
        pk2 INT, 
        pk3 INT, 
        col1 INT, 
        PRIMARY KEY(pk1, pk2, pk3)
      ) WITH (
        orientation = 'row',
        distribution_key = 'pk1,pk2',
        clustering_key = 'pk1:asc,pk2:asc,pk3:asc'
      );
      
      -- データを書き込みます。
      INSERT INTO test_scan VALUES (1,2,3,4),(1,2,5,6),(1,2,7,8);
      
      -- offset + limit をサポートします。PrefixScan に基づき、指定された行から始まる特定の数の行を返します。
      SET hg_experimental_enable_fixed_dispatcher_for_scan = on;
      -- デフォルトでは、結果は pk3 の昇順でソートされます。
      SELECT * FROM test_scan WHERE pk1 = 1 AND pk2 = 2 OFFSET 1 limit 2;
    • 降順でのページ分割結果

      -- テーブルを作成します。
      CREATE TABLE test_scan(
        pk1 INT, 
        pk2 INT, 
        pk3 INT, 
        col1 INT, 
        PRIMARY KEY(pk1, pk2, pk3)
      ) WITH (
        orientation = 'row',
        distribution_key = 'pk1,pk2',
        clustering_key = 'pk1:asc,pk2:asc,pk3:desc'
      );
      
      -- データを書き込みます。
      INSERT INTO test_scan VALUES (1,2,3,4),(1,2,5,6),(1,2,7,8);
      
      -- 以下の 2 つの GUC を有効にします。結果は pk3 の降順でソートされます。
      SET hg_experimental_enable_fixed_dispatcher_for_scan = on;
      SET hg_experimental_enable_fixed_dispatcher_for_clustering_key_scan = on;
      SELECT * FROM test_scan WHERE pk1 = 1 AND pk2 = 2 OFFSET 1 limit 2;

COPY シナリオ

Hologres V1.3.17 以降、COPY ステートメントは Fixed Plan をサポートします。この機能は Fixed Copy と呼ばれます。COPY と Fixed Copy の比較については、「バッチ書き込みモードの比較」をご参照ください。

Fixed Copy のパラメーター設定の詳細については、「COPY」をご参照ください。以下の例はコマンドを示しています。

COPY table_name (column0, column1, column2)
FROM
    STDIN WITH (
        format BINARY,
        stream_mode TRUE,
        on_conflict UPDATE);

すべての列が指定されていない場合の動作。

  • `COPY` コマンドが列のサブセットに書き込む場合、以下のように部分更新を実行します:

    CREATE TABLE t0 (
        id INT NOT NULL,
        name TEXT,
        age INT,
        PRIMARY KEY (id)
    );
    
    COPY t0 (id,
        name)
    FROM
        STDINWITH (stream_mode TRUE, on_conflict UPDATE);
    
    -- 上記の COPY ステートメントは、以下のステートメントと同等です
    INSERT INTO t0 (id, name)
        VALUES (?, ?)
    ON CONFLICT (id)
        DO UPDATE SET id = excluded.id, name = excluded.name;
  • `COPY` コマンドが列のサブセットに書き込み、書き込まれていない列にデフォルト値がある場合、動作は以下のようになります:

    CREATE TABLE t0 (
        id INT NOT NULL,
        name TEXT,
        age INT DEFAULT 0,
        PRIMARY KEY (id)
    );
    
    COPY t0 (id,
        name)
    FROM
        STDINWITH (stream_mode TRUE, on_conflict UPDATE);
    
    -- 上記の COPY ステートメントは、以下の INSERT INTO ステートメントと同等です。
    -- id データが存在しない場合、age 列にはデフォルト値が割り当てられます。
    -- id データが既に存在する場合、age 列は更新されません。
    INSERT INTO t0 (id, name, age)
        VALUES (?, ?, DEFAULT)
    ON CONFLICT (id)
        DO UPDATE SET id = excluded.id, name = excluded.name;
    

式に対する Fixed Plan のサポート

Hologres V3.2 以降、Fixed Plan は式を含む SQL ステートメントをサポートします。PostgreSQL の式の詳細については、「PostgreSQL Expressions」をご参照ください。式は以下のシナリオでサポートされます:

  • INSERT ステートメント:

    • VALUES 句。

    • INSERT ON CONFLICT DO UPDATE 句。

    • INSERT ON CONFLICT WHERE 句のフィルター条件。

    • RETURNING 句。

  • SELECT ステートメント

    SELECT リストのフィールド。

制限事項

  • スカラー式とスカラー関数のみがサポートされます。集計関数、ウィンドウ関数、またはサブクエリはサポートされていません。

  • INSERT ステートメントの場合、VALUES 句以外の句の式または関数は、Hologres クエリエジンで実行可能でなければなりません。

  • SELECT ステートメントの場合、IMMUTABLE な式と関数のみがサポートされます。関数は定数入力パラメーターもサポートする必要があります。

  • この機能を使用するには、以下のパラメーターを有効にする必要があります:

    -- セッションレベルで有効にします。
    SET hg_experimental_enable_fixed_plan_expression = on;
    
    -- DB レベルで有効にします。
    ALTER DATABASE <db_name> SET hg_experimental_enable_fixed_plan_expression = on;

使用例

  • 4 種類の INSERT 句における式

    -- テーブルを作成します。
    CREATE TABLE test_t (
        id INT PRIMARY KEY,
        col INT,
        ts TIMESTAMP
    )
    WITH (
        orientation = 'row',
        distribution_key = 'id'
    );
    
    -- GUC を有効にします。
    SET hg_experimental_enable_fixed_plan_expression = ON;
    
    -- values 句に式が含まれています。
    INSERT INTO test_t VALUES (1, 1, now());
    
    -- on conflict do update 句に式が含まれています。
    INSERT INTO test_t AS old 
        VALUES (1, 1, now())
        ON CONFLICT (id) 
        DO UPDATE SET col = excluded.col + old.col, ts = excluded.ts;
    
    -- on conflict where 句に式が含まれています。
    INSERT INTO test_t AS old
        VALUES (1, 1, now())
        ON CONFLICT (id)
        DO UPDATE SET col = excluded.col + old.col, ts = excluded.ts
        WHERE excluded.ts > old.ts;
    
    -- returning 句に式が含まれています。
    INSERT INTO test_t AS old
        VALUES (1, 1, now())
        ON CONFLICT (id)
        DO UPDATE SET col = excluded.col + old.col, ts = excluded.ts
        WHERE excluded.ts > old.ts
        RETURNING 2 * col, ts;
  • SELECT ステートメントの SELECT リストにおける式

    • 完全なプライマリキーに基づくポイントクエリシナリオ:以下の例は、JSONB 列指向フィールドから値を抽出する方法を示しています。

      -- テーブルを作成します。
      CREATE TABLE test_t (
          id int PRIMARY KEY,
          ts TIMESTAMP NOT NULL,
          col JSONB
      )
      WITH (
          orientation = 'row',
          distribution_key = 'id'
      );
      
      -- Select リストに式が含まれています。Jsonb オペレーターがサポートされています。
      SELECT
          (col ->> 'b')::int + (col ->> 'a')::int,
          date_trunc('day', ts)
      FROM
          test_t
      WHERE
          id = 1;
    • 部分的なプライマリキーに基づく PrefixScan シナリオ。

      -- テーブルを作成します。
      CREATE TABLE test_t (
          id INT,
          ts TIMESTAMP NOT NULL,
          col JSONB,
          PRIMARY KEY (id, ts)
      )
      WITH (
          orientation = 'row',
          distribution_key = 'id'
      );
      
      -- GUC を有効にします。
      SET hg_experimental_enable_fixed_dispatcher_for_scan = TRUE;
      
      -- Select リストに式が含まれています。
      SELECT
          (col ->> 'b')::int + (col ->> 'a')::int,
          date_trunc('day', ts)
      FROM
          test_t
      WHERE
          id = 1;
  • SELECT ステートメントの場合、非 IMMUTABLE 関数や定数入力パラメーターをサポートしない関数が関与するシナリオでは、Fixed Plan の最適化は使用できません。

    -- テーブルを作成します。
    CREATE TABLE test_t (
        id INT PRIMARY KEY,
        ts TIMESTAMP NOT NULL,
        col JSONB
    )
    WITH (
        orientation = 'row',
        distribution_key = 'id'
    );
    
    -- random() 関数は不変ではなく、Fixed Plan ではサポートされていません。
    SELECT
        id + random()
    FROM
        test_t
    WHERE
        id = 1;
    
    -- toString 関数は定数入力パラメーターをサポートしておらず、Fixed Plan ではサポートされていません。
    SELECT
        toString (id)
    FROM
        test_t
    WHERE
        id = 1;

Fixed Plan の検証

  • INSERT、UPDATE、DELETE 操作を含む、Fixed Plan を使用して実行されるデータを変更する SQL ステートメントは、コンソールのリアルタイムインポート RPS パネルに SDK タイプとして表示されます。データ更新効率を向上させるために、INSERT、UPDATE、DELETE などのリアルタイム書き込み操作を Fixed Plan を使用するように最適化することを推奨します。以下の図は、モニタリングメトリックの例を示しています。RPS

  • `EXPLAIN` を使用して SQL 実行計画を表示できます。返された実行計画に FixedXXXNode が含まれている場合、Fixed Plan がトリガーされたことを示します (以下の図を参照)。生成された実行計画に FixedXXXNode が含まれていない場合は、前のセクションで説明した条件が満たされているか確認してください。验证fixedplan

パフォーマンスチューニング

Fixed Plan を有効にしてもパフォーマンスチューニングが必要な場合は、以下の方法を使用できます。

  • Hologres V1.1.49 以降では、Fixed Plan のポイントクエリシナリオのパフォーマンスが最適化されています。大規模なポイントクエリのスループットが 30% 以上向上します。必要に応じて、インスタンスを V1.1.49 以降にアップグレードできます。

  • クライアントで適切なバッチサイズを使用します。Holo Client はリクエストを自動的にバッチ処理します。512 または 512 の倍数のバッチサイズを使用すると、パフォーマンスが向上します。

FAQ

  • 質問 1:接続に失敗し、role/database does not exist. というエラーが表示されます。

    • 原因:ユーザーまたはデータベースが存在しません。

    • 解決策:接続情報を確認し、正しいユーザー名またはデータベース名を入力してください。

      Hologres 管理コンソールにログインし、対象のインスタンスを見つけ、Actions 列の Manage をクリックし、次に Database Management をクリックします。Users および Database Authorization ページでユーザー名またはデータベース名を確認できます。

  • 質問 2:データ書き込み中に the requested table name: xxx (id: xx, version: xx) mismatches the version of the table (id: xx, version: xx) from server. というエラーが発生します。

    • 原因:データ書き込みプロセス中にテーブルのメタデータが変更されました。たとえば、列が追加されたなどです。これにより、テーブルのバージョンが変更されました。

    • 解決策:接続を再確立してください。Fixed Plan は新しいテーブルメタデータを取得し、書き込み操作を実行します。