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 イニシャライザーに登録する必要があります。
