Hvordan kan man oversette forretningskrav til konkrete datastukturer ved Ă„ designe en database for en meldingsapp fra bunnen av.
- Del 1: Designer rammeverket for databasen

VĂ„r database vil ikke vĂŠre sĂ„ stor og distribuert, eller , men «bare for Ă„ ha noe», men det skal vĂŠre bra â funksjonelt, raskt og fĂ„ plass pĂ„ Ă©n server PostgreSQL â slik at man kan sette opp en egen tjeneste et annet sted, for eksempel.
Derfor skal vi ikke ta opp spÞrsmÄl om sharding, replikering og geo-distribuerte systemer, men fokusere pÄ skjematiske lÞsninger inne i databasen.
Trinn 1: Litt forretningsspesifikke detaljer
Vi vil designe meldingsutvekslingen ikke abstrakt, men integrere den i konteksten av . Det vil si at folk ikke «bare skriver til hverandre», men kommuniserer i sammenheng med Ä lÞse spesifikke forretningsoppgaver.
Og hvilke oppgaver har virksomheter?... La oss se pĂ„ et eksempel med Vasily â lederen for utviklingsavdelingen.
- «Nikolai, vi trenger en patch for denne oppgaven i dag!»
Dermed kan samtalen foregÄ i konteksten av en eller annen dokumentet. - «Kola, la oss spille Dota i kveld?»
SÄ selv med ett par samtalepartnere kan kommunikasjonen skje om flere temaer. - «Petr, Nikolai, se vedlegget for prisen pÄ den nye serveren.»
Dermed kan en melding ha flere mottakere. I tillegg kan meldingen inneholde vedlagte filer. - «Semen, og du ogsÄ, ta en titt.»
Og det mÄ vÊre mulig Ä invitere en ny deltaker til en allerede eksisterende samtale Vi stopper forelÞpig med denne listen over «Äpenbare» behov..
Uten Ä forstÄ den praktiske spesifikasjonen av oppgaven og de begrensningene den setter, er det nesten umulig Ä designe
en effektiv databasestruktur for Ă„ lĂžse den. Trinn 2: Minimal logisk plan
SĂ„ langt ser den skjematiske fremstillingen veldig lik e-postkorrespondanse ut â et tradisjonelt verktĂžy for forretning. Ja, «algoritmisk» er mange forretningsoppgaver like, sĂ„ verktĂžyene for Ă„ lĂžse dem vil vĂŠre strukturelt like.
La oss fastholde den logiske planen for entitetenes forhold vi allerede har fÄtt. For enkelhets skyld i vÄr modell vil vi bruke den enkleste varianten av representasjonen
ER-modellen uten kompliserte UML- eller IDEF-notasjoner:

I vÄrt eksempel er persona, dokumentet og det binÊre «kropp» av filen «eksterne» enheter som eksisterer uavhengig av vÄr tjeneste. SÄ vi vil bare oppfatte dem videre som noen lenker «et sted» via UUID.
Tegn diagrammer sĂ„ enkelt som mulig â de fleste som du vil vise dem til, er ikke eksperter pĂ„ Ă„ lese UML/IDEF. Men â husk Ă„ tegne.
Trinn 3: Utkast til tabellstrukturen
Om navnene pÄ tabeller og feltMan kan se pÄ «russiske» navne pÄ felt og tabeller pÄ forskjellige mÄter, men det er en smaksak. Siden ikke har utenlandske utviklere, og PostgreSQL lar oss gi navn selv i hieroglyfer, hvis de er innesluttet i anfÞrselstegn, sÄ foretrekker vi Ä navngi objekter klart og entydig for Ä unngÄ misforstÄelser.
Siden mange personer skriver meldinger samtidig, kan noen av dem faktisk gjĂžre dette i offline-modus, sĂ„ det enkleste alternativet er Ă„ bruke UUID som identifikatorer ikke bare for eksterne enheter, men ogsĂ„ for alle objekter innen vĂ„r tjeneste. Og de kan genereres til og med pĂ„ klientsiden â dette vil hjelpe oss Ă„ stĂžtte sending av meldinger ved kortvarig databaseutilgjengelighet, og sjansen for kollisjon er ekstremt lav.
Den forelÞpige tabellstrukturen i databasen vÄr vil se slik ut:
Tabeller : RU
CREATE TABLE "Tema"(
"Tema"
uuid
PRIMARY KEY
, "Dokument"
uuid
, "Navn"
text
);
CREATE TABLE "Melding"(
"Melding"
uuid
PRIMARY KEY
, "Tema"
uuid
, "Forfatter"
uuid
, "DatoTid"
timestamp
, "Tekst"
text
);
CREATE TABLE "Mottaker"(
"Melding"
uuid
, "Persona"
uuid
, PRIMARY KEY("Melding", "Persona")
);
CREATE TABLE "Fil"(
"Fil"
uuid
PRIMARY KEY
, "Melding"
uuid
, "BLOB"
uuid
, "Navn"
text
);Tabeller : 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
);Det enkleste ved beskrivelsen av formatet er Ä begynne Ä «puste liv» i forbindelser fra tabeller som ikke refererer til noen andre.
Trinn 4: Avdekke ikke-Äpenbare behov
Vi har designet en database hvor det er lett Ä skrive og pÄ en eller annen mÄte lese.
La oss sette oss i brukeren sin plass â hva vil vi Ăžnsker Ă„ gjĂžre med hjelp av tjenesten?
- Siste meldinger
Dette chronologisk sortert etter ulike kriterier en liste over «mine» meldinger. Der jeg er en av mottakerne, der jeg er forfatter, der jeg har fÄtt en melding, men ikke svart, hvor jeg ikke har fÄtt svar, ⊠- Deltakere i samtalen
Hvem deltar i denne lange, lange chatten?
VĂ„r struktur lar oss lĂžse begge disse oppgavene «generelt», men raskt â nei. Problemet er at for sortering i forbindelse med den fĂžrste oppgaven er det umulig Ă„ lage en indeks, som er passende for hver deltaker (og vi mĂ„ hente ut alle oppfĂžringer), mens for Ă„ lĂžse den andre mĂ„ vi hente ut alle meldinger om emnet.
Uforutsigbare brukeroppgaver kan sette en stor brems pÄ ytelsen.
Steg 5: Fornuftig denormalisering
Begge vÄre problemer kan lÞses med ekstra tabeller, hvor vi skal duplisere deler av dataene, som er nÞdvendige for Ä lage passende indekser for vÄre oppgaver.

Tabeller : RU
CREATE TABLE "Meldingsregister"(
"Eier"
uuid
, "Registertype"
smallint
, "DatoTid"
timestamp
, "Melding"
uuid
, PRIMARY KEY("Eier", "Registertype", "Melding")
);
CREATE INDEX ON "Meldingsregister"("Eier", "Registertype", "DatoTid" DESC);
CREATE TABLE "TemaDeltaker"(
"Tema"
uuid
, "Person"
uuid
, PRIMARY KEY("Tema", "Person")
);Tabeller : 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)
);Her har vi brukt to typiske tilnĂŠrminger, som brukes ved opprettelse av hjelpe-tabeller:
- Multiplikasjon av poster
Vi lager flere konsekvensoppfĂžringer av en enkelt originalmelding i forskjellige registertyper for forskjellige eiere â bĂ„de for avsender og mottaker. NĂ„ ligger imidlertid hver av registrene pĂ„ indeks â for i typiske tilfeller Ăžnsker vi vanligvis kun Ă„ se den fĂžrste siden. - Unikalisering av oppfĂžringer
Ved hver sending av melding innad i et bestemt tema er det tilstrekkelig Ă„ sjekke om en slik oppfĂžring allerede eksisterer. Hvis ikke â legger vi den til vĂ„r «ordbok».
I neste del av artikkelen vil vi snakke om inn i strukturen i databasen vÄr.
Kilde: habr.com
