メッセンジャー データベースをゼロから設計する例を使用して、ビジネス要件を特定のデータ構造に変換する方法。
- パート 1: ベースフレームの設計
パート 2: 「営利目的」の区分
私たちの拠点はそれほど大きくなく、分散していますが、
したがって、シャーディング、レプリケーション、地理的分散システムの問題には触れず、データベース内の回路ソリューションに焦点を当てます。
ステップ 1: ビジネスの詳細
メッセージングを抽象的に設計するのではなく、環境に統合します。
そして、ビジネスのタスクは何ですか?...開発部門の責任者であるヴァシリーの例を見てみましょう。
- 「ニコライ、このタスクには今日パッチが必要です!」
これは、何らかの状況で通信を行うことができることを意味します。 ドキュメント. - 「コーリャ、今晩Dotaに行きますか?」
つまり、XNUMX 組の対話者でも同時に通信できます。 さまざまな話題について. - 「ピーター、ニコライ、新しいサーバーの価格表の添付ファイルを見てください。」
したがって、XNUMX つのメッセージには次の内容を含めることができます 複数の受信者。 この場合、メッセージには次の内容が含まれる場合があります。 添付ファイル. - 「セミョンさんも見てください」
そして、既存の通信を開始する機会があるはずです 新しいメンバーを招待する.
ここでは、この「明白な」ニーズのリストについて詳しく見ていきましょう。
問題の適用詳細とそれに与えられた制限を理解せずに、設計を行う 効果的 データベース スキーマを使用してそれを解決することはほとんど不可能です。
ステップ 2: 最小限の論理回路
これまでのところ、すべては従来のビジネス ツールである電子メールでのやり取りと非常によく似ています。 はい、多くのビジネス上の問題は「アルゴリズム的に」互いに類似しているため、問題を解決するためのツールも構造的に似ています。
すでに取得されているエンティティ関係の論理図を修正しましょう。 モデルを理解しやすくするために、最も原始的な表示オプションを使用します。
この例では、人物、ドキュメント、およびファイルのバイナリ「本体」は、当社のサービスなしで独立して存在する「外部」エンティティです。 したがって、将来的には、それらを UUID による「どこか」のリンクとして認識するだけになります。
描く できるだけシンプルな図 - あなたが案内する人のほとんどは、UML/IDEF を読む専門家ではありません。 ただし必ず描いてください。
ステップ 3: テーブル構造のスケッチ
テーブル名とフィールド名についてフィールドとテーブルの「ロシア語」名は別の方法で扱うことができますが、これは好みの問題です。 なぜなら
多くの人が一度にメッセージを書いてくるので、中にはこれを行う人もいるかもしれません オフライン、その場合、最も単純なオプションは次のとおりです。 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: スマートな非正規化
どちらの問題も追加のテーブルによって解決されます。 データの重複部分、タスクに適したインデックスを形成するために必要です。
テーブル : 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