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

PostgreSQL11を使用したデータのシャーディング

    PostgreSQLのバージョン10では、宣言型テーブルパーティショニングが追加されました。 機能。バージョン11(現在ベータ版)では、これを外部データラッパーと組み合わせることができます。 、複数のPostgreSQLサーバー間でテーブルをネイティブにシャーディングするメカニズムを提供します。

    宣言型パーティショニング

    毎日の都市の毎日の最低気温と最高気温を保存するテーブルを考えてみましょう。

    CREATE TABLE temperatures (
        at      date,
        city    text,
        mintemp integer,
        maxtemp integer
    );

    テーブルの仕様には、物事を単純にするために列の制約と主要なキーが意図的に含まれていません。これらは後で追加します。

    多くのアプリケーションでは、最新のデータがより頻繁にアクセスされることがよくあります。現在の会計年度、今月、最後の1時間などを考えてみてください。 「温度」テーブルが大きくなるにつれて、古いデータを同じ構造の別のテーブルに移動するのが理にかなっています。たとえば、次のようにすることができます:

    CREATE TABLE temperatures_2017 (LIKE temperatures);
    INSERT INTO temperatures_2017 SELECT * FROM temperatures WHERE
    	extract(year from at) = 2017;
    DELETE FROM temperatures WHERE extract(year from at) = 2017;

    2017年のすべてのエントリを別のテーブルに移動します。これにより、メインの「温度」テーブルが小さくなり、アプリケーションが処理できるようになります。ボーナスとして、古いデータを削除する必要がある場合は、古いデータが存続するため、メイン/現在のテーブルへの受信データの挿入を遅くすることなく削除できます。別のテーブルにあります。

    ただし、複数の個別のテーブルがあるということは、アプリケーションコードを変更する必要があることを意味します。都市の年間最低気温と最高気温を取得するなど、古いデータにアクセスする必要がある場合は、スキーマに存在するテーブルを見つけ、それぞれにクエリを実行し、各テーブルの結果を組み合わせる必要があります。アプリケーションコードを変更せずにこれを行うことはできますか?

    パーティショニングはこれを可能にします。 PostgreSQL 10では、次のような「温度」テーブルを作成できます。

    CREATE TABLE temperatures (
        at      date,
        city    text,
        mintemp integer,
        maxtemp integer
    )
    PARTITION BY RANGE (at);

    これにより、「温度」がパーティションマスターテーブルになり、重複しないデータを格納する複数のパーティションテーブルを作成し、それぞれに異なる「at」値のセットを設定するようにPostgreSQLに通知します。マスターテーブル自体はデータを保持しませんが、アプリケーションからクエリを実行したり、アプリケーションから挿入したりできます。これは、実際のデータを保持している子パーティションを認識しません。

    そして、これが私たちのパーティションです:

    CREATE TABLE temperatures_2017
        PARTITION OF temperatures
        FOR VALUES FROM ('2017-01-01') TO ('2018-01-01');
    
    CREATE TABLE temperatures_2018
        PARTITION OF temperatures
        FOR VALUES FROM ('2018-01-01') TO ('2019-01-01');

    現在、2つのテーブルがあります。1つは2017年のデータを格納し、もう1つは2018年のデータを格納します。「from」の値は含まれますが、「to」の値は含まれないことに注意してください。試してみましょう:

    temp=# INSERT INTO temperatures (at, city, mintemp, maxtemp)
    temp-#        VALUES ('2018-08-03', 'London', 63, 90);
    INSERT 0 1
    temp=# INSERT INTO temperatures (at, city, mintemp, maxtemp)
    temp-#        VALUES ('2017-08-03', 'London', 59, 70);
    INSERT 0 1
    temp=# SELECT * FROM temperatures;
         at     |  city  | mintemp | maxtemp
    ------------+--------+---------+---------
     2017-08-03 | London |      59 |      70
     2018-08-03 | London |      63 |      90
    (2 rows)
    
    temp=# SELECT * FROM temperatures_2017;
         at     |  city  | mintemp | maxtemp
    ------------+--------+---------+---------
     2017-08-03 | London |      59 |      70
    (1 row)
    
    temp=# SELECT * FROM temperatures_2018;
         at     |  city  | mintemp | maxtemp
    ------------+--------+---------+---------
     2018-08-03 | London |      63 |      90
    (1 row)

    「アプリケーション」はメインテーブルに挿入して選択できますが、PostgreSQLは実際のデータを適切な子テーブルにルーティングします。 (ああ、BTW、それらの温度は本物です!)

    インデックスと制約

    インデックスとテーブルおよび列の制約は、実際のデータが存在する場所であるため、実際にはパーティションテーブルレベルで定義されます。パーティションテーブルの作成中にこれらを設定できます:

    CREATE TABLE temperatures_2017
        PARTITION OF temperatures (
            mintemp NOT NULL,
            maxtemp NOT NULL,
            CHECK (mintemp <= maxtemp),
            PRIMARY KEY (at, city)
        )
        FOR VALUES FROM ('2017-01-01') TO ('2018-01-01');

    PostgreSQL 11では、親テーブルにインデックスを定義でき、既存および将来のパーティションテーブルにインデックスを作成します。詳しくはこちらをご覧ください。

    外部データラッパー

    外部データラッパー機能は、しばらくの間Postgresに存在していました。 PostgreSQLでは、このメカニズムを使用して、他のサーバーやシステムに保存されているデータにアクセスできます。私たちが興味を持っているのは「postgres_fdw」です。これにより、あるPostgresサーバーから別のサーバーにアクセスできるようになります。

    「postgres_fdw」は標準ディストリビューションに存在する拡張機能であり、通常のCREATEEXTENSIONコマンドでインストールできます。

    CREATE EXTENSION postgres_fdw;

    「box2db」というデータベースを持つ別のPostgreSQLサーバー「box2」があると仮定します。このための「外部サーバー」を作成できます:

    CREATE SERVER box2 FOREIGN DATA WRAPPER postgres_fdw
        OPTIONS (host 'box2', dbname 'box2db');

    また、ユーザー「alice」(ログインしているユーザー)をbox2ユーザー「box2alice」にマッピングしましょう。これにより、リモートテーブルにアクセスするときに「alice」を「box2alice」にすることができます。

    CREATE USER MAPPING FOR alice SERVER box2
        OPTIONS (user 'box2alice');

    これで、box2のテーブル(ビュー、マットビューなど)にアクセスできます。まず、box2にテーブルを作成し、次にサーバーに「外部テーブル」を作成します。外部テーブルは実際のデータを保持しませんが、テーブルボックス2にアクセスするためのプロキシとして機能します。

    -- on box2
    CREATE TABLE foo (a int);
    
    -- on your server
    IMPORT FOREIGN SCHEMA public LIMIT TO (foo)
        FROM SERVER box2 INTO public;

    サーバー内の外部テーブルは、通常のテーブルと同じ方法でトランザクションに参加できます。アプリケーションは、相互作用するテーブルがローカルまたは外部であることを知る必要はありません。ただし、アプリケーションが外部テーブルから多くの行をプルするSELECTを実行すると、処理速度が低下する可能性があります。Postgres10では、結合をプッシュダウンするための改善が行われました。リモートサーバーに集約します。

    パーティショニングとFDWの組み合わせ

    そして今、楽しい部分です。リモートサーバーにパーティションを設定します。

    まず、box2に物理パーティションテーブルを作成しましょう:

    -- on box2
    CREATE TABLE temperatures_2016 (
        at      date,
        city    text,
        mintemp integer,
        maxtemp integer
    );

    次に、外部テーブルとしてサーバー上にパーティションを作成します。

    CREATE FOREIGN TABLE temperatures_2016
        PARTITION OF temperatures
        FOR VALUES FROM ('2016-01-01') TO ('2017-01-01')
        SERVER box2;

    これで、独自のサーバーから挿入してクエリを実行できます:

    temp=# INSERT INTO temperatures (at, city, mintemp, maxtemp)
    temp-#     VALUES ('2016-08-03', 'London', 63, 73);
    INSERT 0 1
    temp=# SELECT * FROM temperatures ORDER BY at;
         at     |  city  | mintemp | maxtemp
    ------------+--------+---------+---------
     2016-08-03 | London |      63 |      73
     2017-08-03 | London |      59 |      70
     2018-08-03 | London |      63 |      90
    (3 rows)
    
    temp=# SELECT * FROM temperatures_2016;
         at     |  city  | mintemp | maxtemp
    ------------+--------+---------+---------
     2016-08-03 | London |      63 |      73
    (1 row)

    あります!バージョン11では、リモートパーティションに行を挿入できるようになりました。この機能により、データを論理的(パーティション)および物理的(FDW)にシャーディングできるようになりました。

    データ管理

    VACUUMやANALYZEなどのコマンドは、パーティションマスターテーブルで期待どおりに機能します。すべてのローカル子テーブルは、VACUUMとANALYZEの対象になります。パーティションを切り離して、データをパーティションの制約なしに操作してから、再接続することができます。子テーブル自体をパーティション化できます。

    データの移動(「再シャーディング」)は、通常のSQLステートメント(挿入、削除、コピーなど)を使用して実行できます。パーティションローカルインデックスとトリガーを作成できます。

    シャードに冗長性を追加することは、論理またはストリーミングレプリケーションで簡単に実現できます。


    1. PostgreSQLエラー:リレーションはすでに存在します

    2. 主キーのインデックスの簡単な使用例

    3. プロバイダーは、Oracleクライアントのバージョンと互換性がありません

    4. SQLServerでのデータ圧縮の概要