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

PostgreSQL 12:外部キーとパーティションテーブル

    PostgreSQL 12がリリースされたので、外部キーはパーティション化されたテーブルと完全に互換性があると見なします。外部キー制約のいずれかの側にパーティションテーブルを設定でき、すべてが正しく機能します。

    なぜ私はこれを指摘するのですか? 2つの理由:最初に、パーティション化されたテーブルがPostgreSQL 10で最初に導入されたとき、それらは外部キーをまったくサポートしていませんでした。パーティションテーブルにFKを作成することも、パーティションテーブルを参照するFKを作成することもできませんでした。第二に、(初期の)テーブル継承機能は実際には外部キーもサポートしていなかったためです。これはすべて、 PostgreSQLで初めて、参照整合性を維持しながら大量のデータを維持できることを意味します。 この機能が完了したので、以前はなかったPostgreSQLの新しいユースケースがいくつか開かれています。

    これは非常に簡単な例です。

    CREATE TABLE items (
        item_id integer PRIMARY KEY,
        description text NOT NULL
    ) PARTITION BY hash (item_id);
    CREATE TABLE items_0 PARTITION OF items FOR VALUES WITH (modulus 3, remainder 0);
    CREATE TABLE items_1 PARTITION OF items FOR VALUES WITH (modulus 3, remainder 1);
    CREATE TABLE items_2 PARTITION OF items FOR VALUES WITH (modulus 3, remainder 2);
    
    CREATE TABLE warehouses (warehouse_id integer primary key, location text not null);
    
    CREATE TABLE stock (
        item_id integer not null REFERENCES items,
        warehouse_id integer not null REFERENCES warehouses,
        amount int not null
    ) partition by hash (warehouse_id);
    CREATE TABLE stock_0 PARTITION OF stock FOR VALUES WITH (modulus 5, remainder 0);
    CREATE TABLE stock_1 PARTITION OF stock FOR VALUES WITH (modulus 5, remainder 1);
    CREATE TABLE stock_2 PARTITION OF stock FOR VALUES WITH (modulus 5, remainder 2);
    CREATE TABLE stock_3 PARTITION OF stock FOR VALUES WITH (modulus 5, remainder 3);
    CREATE TABLE stock_4 PARTITION OF stock FOR VALUES WITH (modulus 5, remainder 4);
    

    ここに2つの外部キーがあることがわかります。 1つは通常の(パーティション化されていない)テーブル倉庫を指します 、他はパーティションテーブル itemsを指します 。各外部キーが一度だけ宣言されていることに気づきましたか?

    外部キーに提供させたい2つの基本的な操作があります。まず、 stockに行を挿入した場合 (参照 表)アイテムに対応する行がない または倉庫参照 表)、エラーが発生する必要があります。次に、参照されているテーブルのいずれかの行を削除し、 stockに一致する行がある場合 、その操作も拒否する必要があります。

    どちらも簡単に確認できます:

    INSERT INTO stock values (1, 1, 10);
    ERROR:  insert or update on table "stock_0" violates foreign key constraint "stock_item_id_fkey"
    DETAIL:  Key (item_id)=(1) is not present in table "items".
    

    良い。次に、参照されるテーブルと参照する行の両方に一致する行を挿入できます。その後、参照されているテーブルのいずれかでの削除は、期待どおりに失敗します。

    INSERT INTO items VALUES (1, 'item 1');
    INSERT INTO warehouses VALUES (1, 'The moon');
    INSERT INTO stock VALUES (1, 1, 10);
    
    DELETE FROM warehouses;
    ERROR:  update or delete on table "warehouses" violates foreign key constraint "stock_warehouse_id_fkey" on table "stock"
    DETAIL:  Key (warehouse_id)=(1) is still referenced from table "stock".
    
    DELETE FROM items;
    ERROR:  update or delete on table "items_2" violates foreign key constraint "stock_item_id_fkey3" on table "stock"
    DETAIL:  Key (item_id)=(1) is still referenced from table "stock".
    

    (もちろん、 UPDATE 前者の操作はINSERTと同じです。 、後者の操作の場合は、 DELETEと同じです。 — UPDATE の場合、元のタプルと変更されたタプルの両方をチェックする必要があることを意味します 外部キーに含まれる列を変更します。)

    これらの例が経験豊富なユーザーにとって不十分に見える場合、それはこれらが太古の昔から通常の(パーティション化されていない)テーブルでもまったく同じように機能するためです。

    実際の使用では、 stockの参照列にインデックスが必要になります 参照されているテーブルを変更した場合は、テーブル。これは、サーバーがエラーなどをスローすることを知るために、それらの参照行を見つける必要があるためです。これは、パーティション化された参照テーブルを使用して簡単に行うことができます。

    CREATE INDEX ON stock (item_id);
    CREATE INDEX ON stock (warehouse_id);
    

    この投稿では、外部キーの基本と、通常のテーブルと同じようにパーティション化されたテーブルでそれらを使用する方法を示しました。後続の投稿では、それらのいくつかの追加機能について説明します。このPostgreSQL12の改善が気に入ったら、コメントで知らせてください!


    1. 空のオブジェクトのjson列をクエリする方法は?

    2. MySQLでサーバー照合を表示する方法

    3. IDを使用して複数の行を削除しますか?

    4. Oracleで日付をフォーマットする方法