Messenger база данни (част 1): проектиране на основната рамка

Как можете да преведете бизнес изискванията в специфични структури от данни, като използвате примера за проектиране на месинджър база данни от нулата.

Messenger база данни (част 1): проектиране на основната рамка
Нашата база няма да е толкова голяма и разпръсната, като ВКонтакте или Badoo, но „така че беше“, но беше добро - функционално, бързо и пасват на един сървър PostgreSQL - за да можете да разположите отделно копие на услугата някъде отстрани, например.

Затова няма да засягаме проблемите на шардинга, репликацията и гео-разпределените системи, а ще се съсредоточим върху схемните решения в базата данни.

Стъпка 1: Някои бизнес специфики

Ние няма да проектираме нашите съобщения абстрактно, а ще ги интегрираме в околната среда корпоративна социална мрежа. Тоест нашите хора не „просто си кореспондират“, а комуникират помежду си в контекста на решаване на определени бизнес проблеми.

И какви са задачите на един бизнес?.. Нека да разгледаме примера на Василий, ръководител на отдела за развитие.

  • „Николай, за тази задача имаме нужда от кръпка днес!“
    Това означава, че кореспонденцията може да се води в контекста на някои документ.
  • „Коля, ще ходиш ли на Dota тази вечер?“
    Тоест дори една двойка събеседници могат да комуникират едновременно по различни теми.
  • „Петър, Николай, вижте в прикачения файл ценовата листа за новия сървър.“
    Така че едно съобщение може да има няколко получатели. В този случай съобщението може да съдържа Прикачени файлове.
  • — Семьон, погледни и ти.
    И трябва да има възможност за влизане в съществуваща кореспонденция поканете нов член.

Нека засега се спрем на този списък с „очевидни“ нужди.

Без разбиране на приложната специфика на проблема и дадените му ограничения проект ефективен схема на база данни за решаването му е почти невъзможно.

Стъпка 2: Минимална логическа схема

Досега всичко работи много подобно на имейл кореспонденцията - традиционен бизнес инструмент. Да, „алгоритмично“ много бизнес проблеми са подобни един на друг, следователно инструментите за решаването им ще бъдат структурно подобни.

Нека коригираме вече получената логическа диаграма на връзките на обектите. За да направим нашия модел по-лесен за разбиране, ще използваме най-примитивната опция за показване ER модели без усложненията на UML или IDEF нотациите:

Messenger база данни (част 1): проектиране на основната рамка

В нашия пример лицето, документът и двоичното „тяло“ на файла са „външни“ обекти, които съществуват независимо без нашата услуга. Следователно ние просто ще ги възприемаме в бъдеще като някакви връзки „някъде“ от UUID.

Рисувам възможно най-прости диаграми - повечето от хората, на които ще ги покажете, не са експерти в четенето на UML/IDEF. Но не забравяйте да рисувате.

Стъпка 3: Скициране на структурата на масата

Относно имената на таблици и полета„Руските“ имена на полета и таблици могат да се третират по различен начин, но това е въпрос на вкус. Тъй като тук в Tensor няма чуждестранни разработчици и 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
);

Маси: EN

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: Открийте неочевидни нужди

Това е всичко, създадохме база данни, в която можете да пишете перфектно и някак си да чета.

Нека се поставим на мястото на потребителя на нашата услуга – какво искаме да правим с нея?

  • Последни съобщения
    То хронологично подредени регистър на „моите“ съобщения въз основа на различни критерии. Къде съм един от получателите, къде съм автор, къде са ми писали и не съм отговорил, къде не са ми отговорили, ...
  • Участници в кореспонденцията
    Кой изобщо участва в този дълъг, дълъг чат?

Нашата структура ни позволява да решим и двата проблема „като цяло“, но не бързо. Проблемът е, че за сортиране в рамките на първата задача не може да създаде индекс, подходящ за всеки от участниците (и ще трябва да извлечете всички записи), а за решаване на втория трябва извлечете всички съобщения по тази тема.

Нежеланите потребителски задачи могат да бъдат удебелени кръст върху производителността.

Стъпка 5: Интелигентна денормализация

И двата ни проблема ще бъдат решени чрез допълнителни таблици, в които ще дублирана част от данните, необходими за формиране на индекси, подходящи за нашите задачи.
Messenger база данни (част 1): проектиране на основната рамка

Маси : RU

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

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

Маси: EN

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)
);

Тук сме приложили два типични подхода, използвани при създаване на спомагателни таблици:

  • Умножаване на записи
    Използвайки един начален запис на съобщение, създаваме няколко последващи записа в различни типове регистри за различни собственици - както за подателя, така и за получателя. Но всеки от регистрите сега попада в индекса - в края на краищата в типичен случай ще искаме да видим само първата страница.
  • Уникални записи
    Всеки път, когато изпращате съобщение в конкретна тема, е достатъчно да проверите дали такъв запис вече съществува. Ако не, добавете го към нашия „речник“.

В следващата част на статията ще говорим за изпълнение на разделяне в структурата на нашата база данни.

Източник: www.habr.com

Добавяне на нов коментар