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

Hologres:パーティションテーブルに関するよくある質問

最終更新日:Dec 12, 2025

Hologres V4.0.0-4.0.8 で論理パーティションテーブルをクエリする際に、「duplicate key value violates unique constraint」エラーやデータ欠損が発生するのはなぜですか?

  • V4.0 では、論理パーティションテーブルのマルチパーティションフラッシュ最適化に、クラスターインデックスの実装に関するバグが存在します。このバグにより、AliORC ファイル (列指向テーブルのデータファイル) 内のインデックスが破損する可能性があります。これにより、主に 2 つの問題が発生する可能性があります:

    • データ欠損:不正なクラスターインデックスが原因で、クエリが既存のデータを見つけられない場合があります。

    • プライマリキーの重複:データ更新中に、Hologres が既存のレコードを特定できず、代わりに新しいレコードが挿入されることがあります。これにより、プライマリキー制約に違反し、データが重複します。

  • このバグは、以下の 3 つの条件がすべて満たされた場合にのみ発生します:

    • ご利用の Hologres インスタンスのバージョンが 4.0.0 から 4.0.8 の間である。

    • テーブルが列指向ストレージまたは行列混在ストレージの論理パーティションテーブルである。

    • テーブルにクラスタリングキーが明示的に定義されている。

ソリューション

インスタンスのアップグレード

  • インスタンスを V4.0.9 以降にアップグレードしてください。

  • V4.0.9 では、クエリが不正なインデックスを使用しようとすると、クエリは失敗し、以下のエラーメッセージが返されます:

    clustered_index size [x] incorrect.

インデックスに問題があるテーブルの確認

  • 各データベースで以下の SQL 文を実行し、インデックスが破損しているテーブルを検出します。

    WITH logical_partition_tables AS (
        SELECT DISTINCT 
            p1.table_namespace, 
            p1.table_name
        FROM hologres.hg_table_properties p1
        WHERE p1.property_key = 'logical_partition_columns'
          AND EXISTS (
              SELECT 1
              FROM hologres.hg_table_properties p2
              WHERE p2.table_namespace = p1.table_namespace
                AND p2.table_name = p1.table_name
                AND p2.property_key = 'orientation'
                AND p2.property_value IN ('column', 'row,column', 'column,row')
          )
    ),
    tables_with_pk AS (
        SELECT 
            l.table_namespace,
            l.table_name,
            p.property_value AS pk_expr
        FROM logical_partition_tables l
        JOIN hologres.hg_table_properties p
          ON l.table_namespace = p.table_namespace
         AND l.table_name = p.table_name
        WHERE p.property_key = 'primary_key'
    ),
    partition_cols AS (
        SELECT 
            l.table_namespace,
            l.table_name,
            p.property_value AS part_expr
        FROM logical_partition_tables l
        JOIN hologres.hg_table_properties p
          ON l.table_namespace = p.table_namespace
         AND l.table_name = p.table_name
        WHERE p.property_key = 'logical_partition_columns'
    ),
    all_partitions AS (
        SELECT 
            t.table_namespace,
            t.table_name,
            t.pk_expr,
            pc.part_expr,
            part.partition
        FROM tables_with_pk t
        JOIN partition_cols pc
          ON t.table_namespace = pc.table_namespace
         AND t.table_name = pc.table_name
        CROSS JOIN LATERAL (
            SELECT partition
            FROM hologres.hg_list_logical_partition(
                (t.table_namespace || '.' || t.table_name)::TEXT
            )
        ) AS part
    ),
    split_kv AS (
        SELECT 
            table_namespace,
            table_name,
            pk_expr,
            partition,
            TRIM(SPLIT_PART(kv, '=', 1)) AS col_name,
            TRIM(SPLIT_PART(kv, '=', 2)) AS col_val
        FROM all_partitions,
        UNNEST(STRING_TO_ARRAY(partition, '/')) AS kv
    ),
    final_where AS (
        SELECT 
            table_namespace,
            table_name,
            pk_expr,
            partition,
            STRING_AGG(
                FORMAT('%I = %L', col_name, col_val),
                ' AND '
                ORDER BY col_name
            ) AS where_clause
        FROM split_kv
        GROUP BY table_namespace, table_name, pk_expr, partition
    )
    SELECT
        FORMAT(
            '-- Check PK duplicates in %I.%I, partition: %s' || E'\n' ||
            'SELECT %s, COUNT(1) FROM %I.%I WHERE %s GROUP BY %s HAVING COUNT(1) > 1;',
            table_namespace, table_name, partition,
            pk_expr,
            table_namespace, table_name,
            where_clause,
            pk_expr
        ) AS detection_sql
    FROM final_where
    ORDER BY table_namespace, table_name, partition;
  • 上記の SQL コマンドを実行すると、現在のデータベース内のテーブルに不正なインデックスがあるかどうかを確認するための、他の SQL 文が返されます。

  • 結果のサンプル:image.png

  • SQL 文を実行します。正常に実行された場合、インデックスは正しいです。clustere_index size mismatch エラーが発生した場合、インデックスは破損しています。エラーメッセージで特定されたテーブルについては、完全なコンパクションを実行して、不正なインデックスファイルを修正します:

    SELECT hologres.hg_full_compact_table('schema.table_name','max_file_size_mb=1, reclaim_deleted_data_space = false');
  • コンパクション後、インデックスは正しく再構築されます。影響を受けたテーブルに対して再度上記のチェック文を実行し、修正を確認できます。

プライマリキーが重複しているテーブルの確認

  • 論理パーティションテーブルでは、プライマリキーが重複することがあります。この問題は、duplicate key value violates unique constraint エラーとして、または同じプライマリキーに対して複数のレコードが存在する形で現れることがあります。以下のコードを実行してください:

    WITH logical_partition_tables AS (
        SELECT DISTINCT 
            p1.table_namespace, 
            p1.table_name
        FROM hologres.hg_table_properties p1
        WHERE p1.property_key = 'logical_partition_columns'
          AND EXISTS (
              SELECT 1
              FROM hologres.hg_table_properties p2
              WHERE p2.table_namespace = p1.table_namespace
                AND p2.table_name = p1.table_name
                AND p2.property_key = 'orientation'
                AND p2.property_value IN ('column', 'row,column')
          )
    ),
    tables_with_pk AS (
        SELECT 
            l.table_namespace,
            l.table_name,
            p.property_value AS pk_expr
        FROM logical_partition_tables l
        JOIN hologres.hg_table_properties p
          ON l.table_namespace = p.table_namespace
         AND l.table_name = p.table_name
        WHERE p.property_key = 'primary_key'
    ),
    partition_cols AS (
        SELECT 
            l.table_namespace,
            l.table_name,
            p.property_value AS part_expr
        FROM logical_partition_tables l
        JOIN hologres.hg_table_properties p
          ON l.table_namespace = p.table_namespace
         AND l.table_name = p.table_name
        WHERE p.property_key = 'logical_partition_columns'
    ),
    all_partitions AS (
        SELECT 
            t.table_namespace,
            t.table_name,
            t.pk_expr,
            pc.part_expr,
            part.partition
        FROM tables_with_pk t
        JOIN partition_cols pc
          ON t.table_namespace = pc.table_namespace
         AND t.table_name = pc.table_name
        CROSS JOIN LATERAL (
            SELECT partition
            FROM hologres.hg_list_logical_partition(
                (t.table_namespace || '.' || t.table_name)::TEXT
            )
        ) AS part
    ),
    split_kv AS (
        SELECT 
            table_namespace,
            table_name,
            pk_expr,
            partition,
            TRIM(SPLIT_PART(kv, '=', 1)) AS col_name,
            TRIM(SPLIT_PART(kv, '=', 2)) AS col_val
        FROM all_partitions,
        UNNEST(STRING_TO_ARRAY(partition, '/')) AS kv
    ),
    final_where AS (
        SELECT 
            table_namespace,
            table_name,
            pk_expr,
            partition,
            STRING_AGG(
                FORMAT('%I = %L', col_name, col_val),
                ' AND '
                ORDER BY col_name
            ) AS where_clause
        FROM split_kv
        GROUP BY table_namespace, table_name, pk_expr, partition
    )
    SELECT
        FORMAT(
            '-- Check PK duplicates in %I.%I, partition: %s' || E'\n' ||
            'SELECT %s, COUNT(1) FROM %I.%I WHERE %s GROUP BY %s HAVING COUNT(1) > 1;',
            table_namespace, table_name, partition,
            pk_expr,
            table_namespace, table_name,
            where_clause,
            pk_expr
        ) AS detection_sql
    FROM final_where
    ORDER BY table_namespace, table_name, partition;
    
  • これらのコマンドを実行すると、現在のデータベース内のテーブルにプライマリキーの重複があるかどうかを確認するための、他の SQL 文が返されます。

  • 結果のサンプル:

    image.png

  • 返された SQL コマンドを実行してデータが返された場合、プライマリキーの重複が存在します。フルコンパクションを実行し、重複したプライマリキーを削除してください。

    -- ステップ 1
    select hologres.hg_full_compact_table('schema.table_name','max_file_size_mb=1');
    -- ステップ 2
    call public.hg_remove_duplicated_pk('schema.table_name','max_file_size_mb=1');
    -- 注:hg_remove_duplicated_pk の実行時に「Query exceed memory limit」エラーが返された場合、データ量が大きすぎて処理できません。この場合、パーティションごとに重複を削除します。前のステップの SQL コメントには、重複データを含むパーティションが示されています。
    call public.hg_remove_duplicated_pk('schema.table_name_1', 'dt_int=1');
    call public.hg_remove_duplicated_pk('schema.table_name_2', 'dt_text=''A''');
  • 操作が完了すると、重複データは削除されます。対応するテーブルに対して再度上記のチェック文を実行し、修正を確認できます。

潜在的な問題があるテーブルの確認

  • 以前のチェックで問題なく通過した場合でも、クラスタリングキーがないテーブルに対して追加のチェックを行うことを選択できます。このようなテーブルはプライマリキーの重複が発生しやすく、書き戻し後のリアルタイムクエリで `cluster index` size mismatch エラーが発生する可能性があります。これらの潜在的なリスクに対処するため、以下の SQL コマンドを使用して影響を受ける可能性のあるテーブルを特定し、それらに対してフルコンパクションを実行してください。

    SELECT
        FORMAT(
           'SELECT hologres.hg_full_compact_table(%L, ''max_file_size_mb=1''); -- Table: %I.%I (has logical partition but NO clustering_key)',
          table_namespace || '.' || table_name,
          table_namespace,
          table_name
        ) AS compact_sql
    FROM (
      SELECT DISTINCT 
      p1.table_namespace, 
      p1.table_name
      FROM hologres.hg_table_properties p1
      WHERE p1.property_key = 'logical_partition_columns'
      AND EXISTS (
        SELECT 1
        FROM hologres.hg_table_properties p2
        WHERE p2.table_namespace = p1.table_namespace
        AND p2.table_name = p1.table_name
        AND p2.property_key = 'orientation'
        AND p2.property_value IN ('column', 'row,column')
      )
    ) AS tables_missing_ck
    ORDER BY table_namespace, table_name;
  • 上記の SQL 文は、フルコンパクションコマンドを生成します。

  • 結果のサンプル:

    image.png

  • オフピーク時にコマンドを実行してください。