パーティションテーブル作成の実装について

SQL

CREATE TABLE measurement (
    city_id     int not null,
    logdate     date not null,
    data        text
) PARTITION BY RANGE (logdate);

CREATE TABLE p1 PARTITION OF measurement
    FOR VALUES FROM ('2020-01-01') TO ('2020-02-01');

構文解析構造

CreateStmt *node = makeNode(CreateStmt);
node->relation = $4; /* ここでは `p1` */
node->inhRelations = list_make1($7); /* ここでは `measurement` */
node->partbound = $9; /* ('2020-01-01') TO ('2020-02-01') */
/* その他の属性は関係ない */

実行処理

DDL文は関数 ProcessUtilitySlow によって処理されます。 T_CreateStmt の場合:

  • パース解析を transformCreateStmt を通じて実行
  • 変換後、作成ステートメントには3つのタイプがあります:
    • CreateStmt
    • CreateForeignTableStmt
    • TableLikeClause

この中で CreateStmt に焦点を当てます。

  • 関数 DefineRelation を使用してテーブルを作成
  • ddl_command_end イベントを記録
  • toast テーブルの reloptions を解析・検証
  • toast テーブルの存在確認と作成

DefineRelation

  • 関係を作成する名前空間を検索し、権限を確認し、同時に削除操作からロックし、一時的な名前空間が選択された場合は stmt->relation を RELPERSISTENCE_TEMP としてマーク
  • 親テーブルの OID リストを記録し、親テーブルをロック
  • 使用するテーブルスペースを選択
  • データベースのデフォルトを使用しない限り、権限をチェック
  • すべての場合で、ユーザー関係を pg_global に配置することを禁止
  • テーブルの所有者となるユーザIDを特定
  • 再オプションの解析と検証(存在する場合)
  • 継承祖先を検索し、継承属性を含む関係スキーマを生成
  • 関係スキーマからタプル記述子を作成
  • デフォルト値を持つ列を特定し、デフォルト挿入の準備を行う
  • アクセスメソッドが指定されていないが、関係タイプに必要な場合はデフォルトを使用
  • 関数 heap_create_with_catalog を使用して関係を作成
  • 関数 CommandCounterIncrement を使用して新規関係を可視化
  • 新しい列のデフォルトおよび生成式を新規関係に追加
  • パーティショニングのために「列生成式」を可視化
  • 既存のデフォルトパーティションが存在する場合、AccessExclusiveLock でロックします。その理由は以下の通りです。
  • 関数 transformPartitionBound を使用して境界値を変換
  • 新しいパーティションの境界が有効であり、親パーティションとの重複がないことを確認
  • デフォルトパーティションが存在する場合、既存の行が新しく追加されるパーティションに属すべきかどうかを確認。該当する行があればエラーを発生
  • パーティション境界を pg_class エントリに保存
  • システムカタログを適切な継承情報で更新
  • パーティションを作成する場合、親で定義されたインデックス、トリガー、外部キーをすべて作成

インデックスは DefineIndex で作成され、トリガーは CloneRowTriggersToPartition で複製され、外部キーは CloneForeignKeyConstraints で複製されます。

  • 新しい CHECK 制約を AddRelationNewConstraints で新規関係に追加
  • 最後に、直接宣言された NOT NULL 制約と親関係から継承された NOT NULL 制約をマージ

タグ: PostgreSQL パーティション DDL テーブル作成 SQL

6月4日 22:14 投稿