CIデータベースに新しいテーブルを追加

パイプライン・データ・パーティショニング設計ブループリントでは、CIドメインの既存のテーブルをパーティショニングする方法を説明します。しかし、新しい機能のテーブルを追加する必要があります。これらのテーブルが、パーティショニングが必要なより大きなテーブルへの参照を保持することもあります。将来の作業を減らすために、パーティショニング可能なテーブルへのbelongs_to 関連付けを使用するすべてのテーブルは、最初からパーティショニングする必要があります。

新しいルーティング・テーブルの作成

データベースヘルパーを使って新しいテーブルと外部キーを作成する例を示します:

  include Gitlab::Database::PartitioningMigrationHelpers
  disable_ddl_transaction!

  def up
    create_table(:p_ci_examples, primary_key: [:id, :partition_id], options: 'PARTITION BY LIST (partition_id)', if_not_exists: true) do |t|
      t.bigserial :id, null: false
      t.bigint :partition_id, null: false
      t.bigint :build_id, null: false
    end

    add_concurrent_partitioned_foreign_key(
      :p_ci_examples, :p_ci_builds,
      column: [:partition_id, :build_id],
      target_column: [:partition_id, :id],
      on_update: :cascade,
      on_delete: :cascade,
      reverse_lock_order: true
    )
  end

  def down
    drop_table :p_ci_examples
  end

このテーブルはルーティングテーブルと呼ばれ、データを保持しません。データはパーティションに格納されます。

ルーティングテーブルを作るとき

  • テーブル名はp_ プレフィックスで始まる必要があります。すべてのクエリがルーティング・テーブルを経由し、パーティションに直接アクセスしないようにするためのアナライザがあります。
  • それぞれの新しいテーブルにはpartition_id 列が必要で、その値は関連するアソシエーションの値と等しくなければなりません。この例では、p_ci_builds です。パイプラインに属するすべてのリソースは、同じpartition_id の値を共有します。
  • 主キーは、id によってのみ効率的に検索できるように、カラムをこのように並べる必要があります。
  • 外部キー制約には、ON UPDATE CASCADE オプションを含める必要があります。これは、partition_id 値がパーティションの再バランスのために更新できる必要があるためです。

最初のパーティションを作成します。

通常、ブート時に最初のパーティションを作成するのはアプリケーションに依存します。しかし、CIテーブルのトラフィックが多く、ノード数が多いため、参照テーブルのロックを取得するのが難しい場合があります。その結果、デプロイ中にノードの起動に失敗することがあります。この失敗を防ぐには、アプリケーションの実行前にパーティションがすでに配置されていることを確認する必要があります:

  disable_ddl_transaction!

  def up
    with_lock_retries do
      connection.execute(<<~SQL)
        LOCK TABLE p_ci_builds IN SHARE ROW EXCLUSIVE MODE;
        LOCK TABLE ONLY p_ci_examples IN ACCESS EXCLUSIVE MODE;
      SQL

      connection.execute(<<~SQL)
        CREATE TABLE IF NOT EXISTS gitlab_partitions_dynamic.ci_examples_100
          PARTITION OF p_ci_examples
          FOR VALUES IN (100);
      SQL
    end
  end

パーティションはgitlab_partitions_dynamic スキーマで作成されます。

パーティションを作成するときは

  • パーティション名にはp_ という接頭辞をつけないこと。
  • partition_id の開始値は100 です。

パーティション値のカスケード

パーティション値をカスケードするには、Ci::Partitionable モジュールを使用する必要があります:

class Ci::Example < Ci::ApplicationRecord
  include Ci::Partitionable

  self.table_name = :p_ci_examples
  self.primary_key = :id

  belongs_to :build, class_name: 'Ci::Build'
  partitionable scope: :build, partitioned: true
end

パーティションの管理

partition_id が正しく伝播されることをテストするために使用されるため、モデルはPARTITIONABLE_MODELS リストに含まれていなければなりません。

これがない場合、partitioned: true を指定すると、最初のパーティションが作成されます。また、モデルはpostgres_partitioning.rb イニシャライザーに登録する必要があります。