sql >> データベース >  >> RDS >> PostgreSQL

データベースレプリケーションをサポートするためのデータ構造設計

    さて、私が最初にすることは、厄介な文字列解析をどこにでもドロップして、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[];
    

    これにより、ストレージスペースが少し増えます。列挙値は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[];
    

    GINインデックスをrep_status_arrayに直接配置できます それがユースケースに役立つ場合でも、クエリを調べて、使用するものに特化したインデックスを作成することをお勧めします。

    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行)に分割したくなるでしょう。私はまだその列挙を使用します:

    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を割り当てます(SELECT *, tableoid FROM t LIMIT 1を試してください )、これは単一のデータベースシステム内の便利な安定した数値識別子です。言い換えると、テーブルを削除して再作成すると(データベースをダンプして復元する場合などに発生する可能性があります)、変更されます。これと同じ理由で、開発と本番で異なる可能性があります。テーブルを追加または名前変更するときに中断する代わりにこれらの状況を機能させたい場合は、OIDの代わりに列挙型を使用してください。

    すべてのレプリケーションに単一のテーブルを使用すると、トリガーやクエリなどを簡単に再利用でき、レプリケーションするデータからほとんどのレプリケーションロジックを切り離すことができます。また、重要な可能性がある単一のインデックスを参照することにより、すべてのオリジンテーブルにわたる特定のホストのステータスに基づいてクエリを実行することもできます。

    テーブルサイズに関しては、PostgreSQLは間違いなく同じテーブル内の1,000万行を処理できます。専用のレプリケーション関連のテーブルを使用した場合は、いつでもパーティションを作成できます。 ホストごと。 (テーブルによるパーティション化は私にはほとんど意味がありません。各アップストリーム行にレプリケーションステータスを格納するよりも悪いようです。)どのようにパーティション化するか、またはそれが適切かどうかは、データベースに尋ねる質問の種類に完全に依存します。ベーステーブルでどのようなアクティビティが発生するか。 (パーティショニングとは、いくつかの大きなブロブではなく、多くの小さなブロブを維持し、単一の操作を実行するために多くの小さなブロブにアクセスする可能性があることを意味します。)ディスクがいつ発生するかを選択するのは本当に重要です。



    1. JDBCを使用して大きなテーブルを反復処理する最速の方法

    2. 保存された日付フィールドを使用して、現在の経過日数を計算するフィールドを計算します

    3. MySQLのパフォーマンス、内部結合、一時およびファイルソートの使用を回避する方法

    4. docker-compose mysqlinitsqlは実行されません