web-dev-qa-db-ja.com

JSONB列または別のテーブルを使用して関係を保存する

私はここを徹底的に検索しようとしましたが、答えは見つかりませんでした。

私は2つのメインテーブルを持つPostgreSQLデータベースを持っています。

  • 書類
  • ユーザー

これらの2つのテーブルには、異なる関係があります。ユーザーは次のことができます。

  • お気に入り
  • ブックマークして後で読む
  • 保存する

... 書類。

問題は、これらの関係をどのように保存すればよいかです。

MySQLでの私の経験では、明白な方法は、user_iddocument_idを含む、これらの多対多の関係のテーブルを作成することでした。

しかし、PostgreSQLを使用していて、驚くほどのJSONがサポートされているため、user_documentuser_id、およびすべての関係を含むJSON列を含むdocument_idテーブルを作成する方がより良いアプローチであると考えています。

JSONは次のようになります。

{
   'follow' : {'date' : 1523517140, 'doesFollow' : 't'}, 
   'bookmark' : {'date' : null, 'doesBookmark' : 'f'},
   ....
}

PostgreSQLの経験はほとんどありませんが、JSONB列に対するクエリのパフォーマンスについてはわかりません。そして、このアプローチがPostgreSQLでまったく意味をなすかどうかはわかりません。しかし、それは問題ないようで、それに何も問題がなければ、おそらく最初の通常のアプローチよりも望ましいでしょう。

1
hamid sajjadi

jsonまたはjsonb(またはxmlまたはhstore)などのドキュメントタイプは、documents。さまざまなキーがあり、ほとんど更新されておらず、クエリが複雑すぎないフィルター条件を持つデータに最適です。データベース内で大量のドキュメントを操作することは、アンチパターンになるでしょう。

ストレージ、パフォーマンス、同時書き込みアクセス、およびデータ整合性に関して、正規化された設計を使用すると、多くの場合小さな増分で書き込まれ、おそらく多くの場合(おそらくあなたの場合のように)検索される構造化データは、はるかに効率的です。したがって マニュアルのアドバイス

JSONデータは、テーブルに格納されるとき、他のデータ型と同じ同時実行制御の考慮事項に従います。大きなドキュメントを保存することは現実的ですが、更新を行うと、行全体で行レベルのロックが取得されることに注意してください。更新トランザクション間のロックの競合を減らすために、JSONドキュメントを管理可能なサイズに制限することを検討してください。理想的には、JSONドキュメントはそれぞれ、ビジネスルールが指示するアトミックデータムを表す必要があり、個別に変更できる小さなデータムにさらに細かく分割することはできません。

1つ以上のジャンクションテーブルとのn:m関係を実装します。制約(PK、FK、UNIQUE、CHECK、..)を使用してデータの整合性を適用できます。 、ドキュメントタイプでは簡単に実現できません。 「いいね」、「ブックマーク」などの要件が大幅に異なる場合を除いて、単一のテーブルを使用します。

例:

一般的なレイアウトが不明な場合は、以下が基本です。

各関係タイプは、ユーザーとドキュメントの組み合わせごとに1回だけ使用できると想定します。ほんの一握りの値(あなたの場合は3)の場合、1バイトの"char"列をルックアップテーブルのPKとして使用して、テーブルとインデックスのストレージとパフォーマンスを最適化します。

CREATE TABLE reltype (
   reltype "char" PRIMARY KEY
 , relation_type text UNIQUE NOT NULL
);

INSERT INTO reltype(reltype, relation_type) VALUES
   ('l', 'like')
 , ('b', 'bookmark')
 , ('s', 'save');

CREATE TABLE user_doc (
   user_doc_id int PRIMARY KEY GENERATED ALWAYS AS IDENTITY
 , user_id     int REFERENCES users     ON UPDATE CASCADE ON DELETE CASCADE
 , document_id int REFERENCES documents ON UPDATE CASCADE ON DELETE CASCADE
 , reltype     "char" REFERENCES reltype NOT NULL DEFAULT 'l'
 , CONSTRAINT user_document_pkey UNIQUE(user_id, document_id, reltype)
);

集計データはいつでもJSONドキュメントとしてエクスポートできます。 VIEWまたはMATERIALIZED VIEWを使用して、テーブルのように読み取ることもできます。ただし、単一の大きなJSONドキュメント内の関係を管理しないでください。

4