私が最初に行うことは、厄介な文字列解析をどこからでも削除し、PostgreSQL のネイティブ型に置き換えることです。現在のソリューションと同様に、各レコードのレプリケーション ステータスを保存するには:
CREATE TYPE replication_status AS ENUM (
'no_action',
'replicate_record',
'record_replicated',
'error_1',
'error_2',
'error_3'
);
ALTER TABLE t ADD COLUMN rep_status_array replication_status[];
これにより、ストレージ容量が少し増えます。enum 値は 1 ではなく 4 バイトであり、配列にはオーバーヘッドがあります。ただし、概念を隠すのではなくデータベースに教えると、次のように記述できます。
-- find all records that need to be replicated to host 4
SELECT * FROM t WHERE rep_status_array[4] = 'replicate_record';
-- find all records that contain any error status
SELECT * FROM t WHERE rep_status_array &&
ARRAY['error_1', 'error_2', 'error_3']::replication_status[];
rep_status_array
それがユースケースに役立つ場合は、GIN インデックスを適切に配置できますが、クエリを調べて、使用するもの専用のインデックスを作成することをお勧めします。
CREATE INDEX t_replication_host_4_key ON t ((rep_status_array[4]));
CREATE INDEX t_replication_error_key ON t (id)
WHERE rep_status_array && ARRAY['error_1', 'error_2', 'error_3']::replication_status[];
とはいえ、200 個のテーブルがある場合、これを 1 つのレプリケーション ステータス テーブルに分割したくなるでしょう。残りのレプリケーション ロジックがどのように機能するかに応じて、ステータスの配列を含む 1 つの行またはホストごとに 1 つの行のいずれかです。私はまだその列挙を使用します:
CREATE TABLE adhoc_replication (
record_id bigint not null,
table_oid oid not null,
host_id integer not null,
replication_status status not null default 'no_action',
primary key (record_id,table_oid,host_id)
);
PostgreSQL は内部的に各テーブルに OID ( try SELECT *, tableoid FROM t LIMIT 1
) を割り当てます。これは、単一のデータベース システム内の便利で安定した数値識別子です。別の言い方をすれば、テーブルが削除されて再作成されると変更されます (たとえば、データベースをダンプして復元すると発生する可能性があります)。これと同じ理由で、開発と運用で異なる可能性が非常に高くなります。テーブルを追加または名前変更するときに、中断と引き換えにこれらの状況を機能させたい場合は、OID の代わりに列挙を使用します。
すべてのレプリケーションに単一のテーブルを使用すると、トリガーやクエリなどを簡単に再利用でき、ほとんどのレプリケーション ロジックをレプリケートしているデータから切り離すことができます。また、単一のインデックスを参照することで、すべての元のテーブルで特定のホストのステータスに基づいてクエリを実行できます。これは重要な場合があります。
テーブルのサイズに関しては、PostgreSQL は間違いなく同じテーブルで 1000 万行を処理できます。専用のレプリケーション関連テーブルを使用した場合は、常にホストごとに分割できます。(テーブルごとのパーティション分割は、私にはほとんど意味がありません。上流の行ごとにレプリケーション ステータスを格納するよりも悪いように思えます。) どの方法でパーティション分割するか、またはそれが適切かどうかは、データベースにどのような質問をするかによって完全に異なります。ベース テーブルで発生するアクティビティの種類。(パーティショニングとは、いくつかの大きな BLOB ではなく、多数の小さな BLOB を維持することを意味し、1 つの操作を実行するために多くの小さな BLOB にアクセスする可能性があります。) ディスク シークをいつ実行するかは、実際には選択の問題です。