Database del messaggero (parte 1): progettazione della struttura del database

Come tradurre le esigenze aziendali in strutture dati concrete, ad esempio progettando da zero il database per il messaggero.

Database del messaggero (parte 1): progettazione della struttura del database
Il nostro database non sarà così grande e distribuito, come quello di VKontakte o Badoo, ma 'solo per avere', ma deve essere buono — funzionale, veloce e che possa stare su un solo server PostgreSQL — per poter distribuire un'istanza separata del servizio da qualche parte, ad esempio.

Pertanto, non tratteremo le questioni di sharding, replicazione e sistemi geograficamente distribuiti, ma ci concentreremo sulle soluzioni schemaliche all'interno del database.

Passo 1: Un po’ di specifiche aziendali

Progetteremo il nostro scambio di messaggi non in modo astratto, ma inserendolo nell'ambiente di una rete sociale aziendale.Cioè, le persone non 'si scambiano solo messaggi', ma comunicano tra loro nel contesto della soluzione di specifici problemi aziendali.

E quali sono le problematiche aziendali? ... Vediamo attraverso l'esempio di Vasiliy — responsabile del reparto sviluppo.

  • 'Nikolai, per questo compito è necessaria la patch già oggi!'
    Significa che la corrispondenza può avvenire nel contesto di qualcosa del documento.
  • «Ciao, andiamo a giocare a Dota stasera?»
    Cioè, anche in una coppia di interlocutori, la conversazione può avvenire simultaneamente su temi diversi.
  • «Pietro, Nicola, date un'occhiata all'allegato con il prezzo del nuovo server.»
    Quindi, un messaggio può avere diversi destinatari. Inoltre, il messaggio può contenere file allegati.
  • «Semion, anche tu dai un'occhiata.»
    E dovrebbe esserci la possibilità di invitare un nuovo partecipante in una conversazione già esistente..

Fermiamoci per ora a questo elenco di esigenze "ovvie".

Senza comprendere la specificità applicativa del compito e i vincoli richiesti, progettare una scheda DB efficace per risolverla è praticamente impossibile.

Passo 2: Schema logico minimo

Finora, tutto sembra molto simile a una corrispondenza via email — uno strumento tradizionale per fare affari. Infatti, «algoritmicamente», molte sfide aziendali sono simili tra loro, quindi anche gli strumenti per risolverle saranno strutturalmente simili.

Fissiamo già lo schema logico delle relazioni tra le entità che abbiamo ottenuto. Per facilitare la comprensione del nostro modello, utilizzeremo la variante più semplice di visualizzazione dei modelli ER senza complicazioni di UML o notazioni IDEF:

Database del messaggero (parte 1): progettazione della struttura del database

Nel nostro esempio, la persona, il documento e il corpo binario del file sono entità "esterne" che esistono autonomamente anche senza il nostro servizio. Pertanto, d'ora in poi le considereremo semplicemente come dei riferimenti "da qualche parte" tramite UUID.

Disegna schemi nel modo più semplice possibile — la maggior parte delle persone a cui li mostrerai non è esperta nella lettura di UML/IDEF. Ma — disegna comunque.

Passo 3: Schizziamo la struttura delle tabelle

Riguardo ai nomi di tabelle e campiAi nomi "russi" dei campi e delle tabelle si può avere un'opinione diversa, ma è una questione di gusto. Poiché nel nostro "Tensor" non ci sono sviluppatori stranieri, e PostgreSQL ci consente di dare nomi anche in geroglifici, se sono racchiusi tra virgolette, preferiamo nominare gli oggetti in modo chiaro e comprensibile, per evitare ambiguità.
Poiché i messaggi vengono scritti simultaneamente da molte persone, alcune di esse possono farlo in modalità offline, l'opzione più semplice è utilizzare UUID come identificatori. non solo per entità esterne, ma anche per tutti gli oggetti all'interno del nostro servizio. Inoltre, è possibile generarle anche dal lato client — questo ci aiuterà a mantenere l'invio di messaggi durante la breve indisponibilità del database, mentre la probabilità di collisione è estremamente bassa.

La struttura di base delle tabelle nel nostro database avrà questo aspetto:
Tabelle : RU

CREATE TABLE "Tema"(
  "Tema"
    uuid
      PRIMARY KEY
, "Documento"
    uuid
, "Titolo"
    text
);

CREATE TABLE "Messaggio"(
  "Messaggio"
    uuid
      PRIMARY KEY
, "Tema"
    uuid
, "Autore"
    uuid
, "DataOra"
    timestamp
, "Testo"
    text
);

CREATE TABLE "Destinatario"(
  "Messaggio"
    uuid
, "Persona"
    uuid
, PRIMARY KEY("Messaggio", "Persona")
);

CREATE TABLE "File"(
  "File"
    uuid
      PRIMARY KEY
, "Messaggio"
    uuid
, "BLOB"
    uuid
, "Nome"
    text
);

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

La cosa più semplice quando si descrive il formato è iniziare a "sviluppare" il grafo delle relazioni da tabelle che non fanno riferimento a nessuno.

Passo 4: Identificare esigenze non evidenti

Bene, abbiamo progettato una base in cui si può scrivere e in qualche modo leggere.

Mettiamoci nei panni dell'utente del nostro servizio: cosa vorremmo fare con il suo aiuto?

  • Ultimi messaggi
    Questo registro 'dei miei' messaggi ordinato cronologicamente per vari criteri. Dove sono uno dei destinatari, dove sono l'autore, dove mi hanno scritto e non ho risposto, dove non mi hanno risposto, …
  • Partecipanti alla conversazione
    Chi partecipa a questa lunga conversazione?

La nostra struttura consente di risolvere entrambe queste questioni 'in generale', ma rapidamente — no. Il problema è che per ordinare nell'ambito del primo compito non è possibile creare un indice, adatto per ognuno dei partecipanti (e sarà necessario estrarre tutte le registrazioni), e per risolvere il secondo è necessario estrarre tutti i messaggi sull'argomento.

Compiti utente non previsti possono compromettere pesantemente le performance..

Passo 5: Denormalizzazione ragionevole

Entrambe le nostre problematiche possono essere affrontate con ulteriori tabelle, in cui duplicheremo parte dei dati , necessari per formare indici adatti alle nostre esigenze., necessari per la creazione di indici adatti ai nostri compiti.
Database del messaggero (parte 1): progettazione della struttura del database

Tabelle : RU

CREATE TABLE "RegistroMessaggi"(
  "Proprietario"
    uuid
, "TipoRegistro"
    smallint
, "DataOra"
    timestamp
, "Messaggio"
    uuid
, PRIMARY KEY("Proprietario", "TipoRegistro", "Messaggio")
);
CREATE INDEX ON "RegistroMessaggi"("Proprietario", "TipoRegistro", "DataOra" DESC);

CREATE TABLE "PartecipanteTema"(
  "Tema"
    uuid
, "Persona"
    uuid
, PRIMARY KEY("Tema", "Persona")
);

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

Qui abbiamo applicato due approcci tipici utilizzati nella creazione di tabelle ausiliarie:

  • Moltiplicazione di record
    Creiamo più record conseguenti da un singolo record originario di messaggio su diversi tipi di registro per diversi proprietari — sia per il mittente che per il destinatario. In questo modo, ciascun registro ora si basa su un indice — in quanto avremmo tipicamente il desiderio di vedere solo la prima pagina.
  • Unificazione dei record
    Ogni volta che un messaggio viene inviato all'interno di un tema specifico, è sufficiente controllare se esiste già un tale record. Se non esiste — lo aggiungiamo al nostro 'glossario'.

Nella prossima parte dell'articolo si parlerà di implementazione della suddivisione nella struttura del nostro database.

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster