Databáze Messenger (část 1): návrh základního rámce

Jak můžete převést obchodní požadavky do konkrétních datových struktur pomocí příkladu návrhu databáze messenger od začátku.

Databáze Messenger (část 1): návrh základního rámce
Naše základna nebude tak velká a distribuovaná, jako VKontakte nebo Badoo, ale "aby to bylo", ale bylo to dobré - funkční, rychlé a vejde na jeden server PostgreSQL - abyste mohli někde na boku nasadit samostatnou instanci služby.

Proto se nebudeme dotýkat problematiky shardingu, replikace a geodistribuovaných systémů, ale zaměříme se na obvodová řešení uvnitř databáze.

Krok 1: Některá obchodní specifika

Nebudeme navrhovat naše zprávy abstraktně, ale integrujeme je do prostředí firemní sociální síť. To znamená, že naši lidé si „jen nedopisují“, ale komunikují spolu v rámci řešení určitých obchodních problémů.

A jaké jsou úkoly podniku?... Podívejme se na příklad Vasilije, vedoucího vývojového oddělení.

  • "Nikolaji, pro tento úkol dnes potřebujeme záplatu!"
    To znamená, že korespondence může být vedena v kontextu některých dokument.
  • "Kolyo, jdeš dnes večer do Doty?"
    To znamená, že i jedna dvojice partnerů může komunikovat současně na různá témata.
  • "Petře, Nikolayi, podívejte se v příloze na ceník nového serveru."
    Takže jedna zpráva může mít několik příjemců. V tomto případě může zpráva obsahovat Přiložené soubory.
  • "Semyone, podívej se taky."
    A měla by být příležitost vstoupit do existující korespondence pozvat nového člena.

Zastavme se nyní u tohoto seznamu „zřejmých“ potřeb.

Bez pochopení aplikovaných specifik problému a omezení, která mu jsou dána, navrhněte efektivní databázové schéma to vyřešit je téměř nemožné.

Krok 2: Minimální logický obvod

Zatím vše funguje velmi podobně jako emailová korespondence – tradiční obchodní nástroj. Ano, „algoritmicky“ je mnoho obchodních problémů navzájem podobných, takže nástroje pro jejich řešení budou strukturálně podobné.

Opravme již získaný logický diagram vztahů entit. Aby byl náš model srozumitelnější, použijeme nejprimitivnější možnost zobrazení ER modely bez komplikací zápisů UML nebo IDEF:

Databáze Messenger (část 1): návrh základního rámce

V našem příkladu jsou osoba, dokument a binární „tělo“ souboru „externí“ entity, které existují nezávisle bez naší služby. Proto je budeme v budoucnu jednoduše vnímat jako nějaké odkazy „někde“ podle UUID.

Nakreslete co nejjednodušší schémata - většina lidí, kterým je ukážete, nejsou odborníci na čtení UML/IDEF. Ale určitě kresli.

Krok 3: Načrtněte strukturu tabulky

O názvech tabulek a políS „ruskými“ názvy polí a tabulek lze zacházet různě, ale to je věc vkusu. Protože tady v Tensoru neexistují žádní zahraniční vývojáři a PostgreSQL nám umožňuje dávat jména i v hieroglyfech, pokud ano uzavřený v uvozovkách, pak objekty raději pojmenováváme jednoznačně a srozumitelně, aby nevznikaly nesrovnalosti.
Protože nám mnoho lidí píše zprávy najednou, někteří z nich to mohou dokonce udělat offline, pak je nejjednodušší možnost používat UUID jako identifikátory nejen pro externí subjekty, ale i pro všechny objekty uvnitř naší služby. Navíc je lze generovat i na straně klienta – to nám pomůže podporovat odesílání zpráv, když je databáze dočasně nedostupná a pravděpodobnost kolize je extrémně nízká.

Návrh struktury tabulky v naší databázi bude vypadat takto:
Tabulky : 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
);

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

Nejjednodušší věcí při popisu formátu je začít „odvíjet“ graf připojení z tabulek, na které se neodkazuje sebe nikomu.

Krok 4: Zjistěte potřeby, které nejsou zřejmé

To je vše, navrhli jsme databázi, do které můžete psát perfektně a Nějak číst.

Vžijme se do kůže uživatele naší služby – co s tím chceme dělat?

  • Poslední zprávy
    To chronologicky řazeny registr „mých“ zpráv na základě různých kritérií. Kde jsem jedním z příjemců, kde jsem autorem, kde mi napsali a já jsem neodpověděl, kde mi neodpověděli, ...
  • Účastníci korespondence
    Kdo se vůbec účastní tohoto dlouhého, dlouhého chatu?

Naše struktura nám umožňuje vyřešit oba tyto problémy „obecně“, ale ne rychle. Problém je v tom, že pro řazení v rámci prvního úkolu nelze vytvořit index, vhodné pro každého z účastníků (a budete muset extrahovat všechny záznamy) a k vyřešení druhého potřebujete extrahovat všechny zprávy na toto téma.

Nezamýšlené uživatelské úkoly mohou být zobrazeny tučně kříž na produktivitu.

Krok 5: Inteligentní denormalizace

Oba naše problémy vyřeší dodatkové tabulky, ve kterých budeme duplicitní část dat, nutné na nich tvořit indexy vhodné pro naše úkoly.
Databáze Messenger (část 1): návrh základního rámce

Tabulky : RU

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

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

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

Zde jsme použili dva typické přístupy používané při vytváření pomocných tabulek:

  • Násobení záznamů
    Pomocí jednoho prvotního záznamu zprávy vytvoříme několik navazujících záznamů v různých typech registrů pro různé vlastníky – jak pro odesílatele, tak pro příjemce. Každý z registrů ale nyní spadá na index – ostatně v typickém případě budeme chtít vidět pouze první stránku.
  • Jedinečné rekordy
    Pokaždé, když posíláte zprávu v rámci konkrétního tématu, stačí zkontrolovat, zda takový záznam již neexistuje. Pokud ne, přidejte jej do našeho „slovníku“.

V další části článku si povíme implementace dělení do struktury naší databáze.

Zdroj: www.habr.com

Přidat komentář