メッセンジャー データベース (パート 1): 基本フレームワークの設計

メッセンジャー データベースをゼロから設計する例を使用して、ビジネス要件を特定のデータ構造に変換する方法。

メッセンジャー データベース (パート 1): 基本フレームワークの設計
私たちの拠点はそれほど大きくなく、分散していますが、 ヴコンタクテのような または Badooメンバー中、しかし「そうだった」、しかしそれは良かった - 機能的で、高速で、そして XNUMX つのサーバーに収まる PostgreSQL - たとえば、サービスの別のインスタンスを別の場所にデプロイできるようにします。

したがって、シャーディング、レプリケーション、地理的分散システムの問題には触れず、データベース内の回路ソリューションに焦点を当てます。

ステップ 1: ビジネスの詳細

メッセージングを抽象的に設計するのではなく、環境に統合します。 企業のソーシャルネットワーク。 つまり、当社の従業員は「ただ対応する」のではなく、特定のビジネス上の問題を解決するという観点から互いにコミュニケーションを取り合います。

そして、ビジネスのタスクは何ですか?...開発部門の責任者であるヴァシリーの例を見てみましょう。

  • 「ニコライ、このタスクには今日パッチが必要です!」
    これは、何らかの状況で通信を行うことができることを意味します。 ドキュメント.
  • 「コーリャ、今晩Dotaに行きますか?」
    つまり、XNUMX 組の対話者でも同時に通信できます。 さまざまな話題について.
  • 「ピーター、ニコライ、新しいサーバーの価格表の添付ファイルを見てください。」
    したがって、XNUMX つのメッセージには次の内容を含めることができます 複数の受信者。 この場合、メッセージには次の内容が含まれる場合があります。 添付ファイル.
  • 「セミョンさんも見てください」
    そして、既存の通信を開始する機会があるはずです 新しいメンバーを招待する.

ここでは、この「明白な」ニーズのリストについて詳しく見ていきましょう。

問題の適用詳細とそれに与えられた制限を理解せずに、設計を行う 効果的 データベース スキーマを使用してそれを解決することはほとんど不可能です。

ステップ 2: 最小限の論理回路

これまでのところ、すべては従来のビジネス ツールである電子メールでのやり取りと非常によく似ています。 はい、多くのビジネス上の問題は「アルゴリズム的に」互いに類似しているため、問題を解決するためのツールも構造的に似ています。

すでに取得されているエンティティ関係の論理図を修正しましょう。 モデルを理解しやすくするために、最も原始的な表示オプションを使用します。 ERモデル UML または IDEF 表記の複雑さなしで:

メッセンジャー データベース (パート 1): 基本フレームワークの設計

この例では、人物、ドキュメント、およびファイルのバイナリ「本体」は、当社のサービスなしで独立して存在する「外部」エンティティです。 したがって、将来的には、それらを UUID による「どこか」のリンクとして認識するだけになります。

描く できるだけシンプルな図 - あなたが案内する人のほとんどは、UML/IDEF を読む専門家ではありません。 ただし必ず描いてください。

ステップ 3: テーブル構造のスケッチ

テーブル名とフィールド名についてフィールドとテーブルの「ロシア語」名は別の方法で扱うことができますが、これは好みの問題です。 なぜなら ここテンソルで 外国の開発者は存在せず、PostgreSQL では象形文字でも名前を付けることができます。 引用符で囲まれたその場合、矛盾がないように、オブジェクトに明確かつ明確に名前を付けることを好みます。
多くの人が一度にメッセージを書いてくるので、中にはこれを行う人もいるかもしれません オフライン、その場合、最も単純なオプションは次のとおりです。 UUIDを識別子として使用する 外部エンティティだけでなく、サービス内のすべてのオブジェクトも対象となります。 さらに、これらはクライアント側でも生成できます。これは、データベースが一時的に利用できず、衝突の可能性が非常に低い場合のメッセージ送信をサポートするのに役立ちます。

データベース内のドラフト テーブル構造は次のようになります。
テーブル : RU

CREATE TABLE "Тема"(
  "Тема"
    uuid
      PRIMARY KEY
, "Документ"
    uuid
, "Название"
    text
);

CREATE TABLE "Сообщение"(
  "Сообщение"
    uuid
      PRIMARY KEY
, "Тема"
    uuid
, "Автор"
    uuid
, "ДатаВремя"
    timestamp
, "Текст"
    text
);

CREATE TABLE "Адресат"(
  "Сообщение"
    uuid
, "Персона"
    uuid
, PRIMARY KEY("Сообщение", "Персона")
);

CREATE TABLE "Файл"(
  "Файл"
    uuid
      PRIMARY KEY
, "Сообщение"
    uuid
, "BLOB"
    uuid
, "Имя"
    text
);

表: JP

CREATE TABLE theme(
  theme
    uuid
      PRIMARY KEY
, document
    uuid
, title
    text
);

CREATE TABLE message(
  message
    uuid
      PRIMARY KEY
, theme
    uuid
, author
    uuid
, dt
    timestamp
, body
    text
);

CREATE TABLE message_addressee(
  message
    uuid
, person
    uuid
, PRIMARY KEY(message, person)
);

CREATE TABLE message_file(
  file
    uuid
      PRIMARY KEY
, message
    uuid
, content
    uuid
, filename
    text
);

フォーマットを記述する際の最も簡単な作業は、接続グラフの「巻き戻し」を開始することです。 参照されていないテーブルから 誰にも自分自身を。

ステップ 4: 明らかではないニーズを見つける

以上です。私たちは、完璧に記述できるデータベースを設計しました。 どういうわけか 読むために。

私たちのサービスのユーザーの立場に立ってみましょう - 私たちはそれを使って何をしたいのでしょうか?

  • 最近の投稿
    それ 時系列に並べた さまざまな基準に基づいた「私の」メッセージのレジストリ。 私が受信者の一人である場合、私が著者である場合、彼らが私に手紙を書いたのに私が返事をしなかった場合、彼らが私に返事をしなかった場合、...
  • 通信の参加者
    この長い長いチャットに参加しているのは誰ですか?

私たちの構造により、これらの問題の両方を「一般的に」解決することができますが、すぐには解決できません。 問題は、最初のタスク内でソートすることです。 インデックスを作成できません、各参加者に適したもの (すべてのレコードを抽出する必要があります)、必要な XNUMX 番目のものを解決します。 すべてのメッセージを抽出する トピックについて

意図しないユーザータスクは太字で表示される場合があります クロスオン生産性.

ステップ 5: スマートな非正規化

どちらの問題も追加のテーブルによって解決されます。 データの重複部分、タスクに適したインデックスを形成するために必要です。
メッセンジャー データベース (パート 1): 基本フレームワークの設計

テーブル : RU

CREATE TABLE "РеестрСообщений"(
  "Владелец"
    uuid
, "ТипРеестра"
    smallint
, "ДатаВремя"
    timestamp
, "Сообщение"
    uuid
, PRIMARY KEY("Владелец", "ТипРеестра", "Сообщение")
);
CREATE INDEX ON "РеестрСообщений"("Владелец", "ТипРеестра", "ДатаВремя" DESC);

CREATE TABLE "УчастникТемы"(
  "Тема"
    uuid
, "Персона"
    uuid
, PRIMARY KEY("Тема", "Персона")
);

表: JP

CREATE TABLE message_registry(
  owner
    uuid
, registry
    smallint
, dt
    timestamp
, message
    uuid
, PRIMARY KEY(owner, registry, message)
);
CREATE INDEX ON message_registry(owner, registry, dt DESC);

CREATE TABLE theme_participant(
  theme
    uuid
, person
    uuid
, PRIMARY KEY(theme, person)
);

ここでは、補助テーブルを作成するときに使用される XNUMX つの典型的なアプローチを適用しました。

  • レコードの増殖
    XNUMX つの初期メッセージ レコードを使用して、送信者と受信者の両方の異なる所有者に応じて、さまざまな種類のレジスターにいくつかのフォローアップ レコードを作成します。 しかし、各レジスタはインデックス上に置かれるようになりました。結局のところ、典型的なケースでは、最初のページだけが必要になります。
  • ユニークなレコード
    特定のトピック内でメッセージを送信するたびに、そのようなエントリが既に存在するかどうかを確認するだけで十分です。 そうでない場合は、「辞書」に追加してください。

記事の次の部分では、次のことについて説明します。 パーティショニングの実装 データベースの構造に組み込まれます。

出所: habr.com

コメントを追加します