Ինչպե՞ս կարելի է բիզնես պահանջները փոխարկել կոնկրետ տվյալների կառուցվածքների, օրինակ, մեսենջերի «ցուցակային» նախագծման մեջ:
- Մաս 1: նախագծում ենք տվյալների բազայի շրջանակը

Մեր տվյալների база չի լինի այնքան մեծ և բաշխված, կամ , այլ «որ լինի», բայց լավ — գործառնական, արագ և տեղավորվի մեկ սերվերի վրա PostgreSQL — որպեսզի հնարավոր լինի ծառայության առանձին օրինակ բացել որտեղ-որ, օրինակ:
Ուստի չենք մտնի շարդինգի, կրկնության և աշխարհագրորեն բաշխված համակարգերի հարցերին, այլ կենտրոնանանք տվյալների բազայի ներքո սխեմայական լուծումների վրա:
Քայլ 1: Փոքր-ինչ բիզնես- specifiek
Մենք մեր հաղորդագրությունների փոխանակումը չենք նախագծում որպես抽象, այլ մենք इसे կցում ենք . Ընդդիմադիր, մարդիկ մեզ մոտ չեն «կոտրվել», այլ շփվում են միմյանց հետ որոշակի բիզնես խնդիրների լուծման համատեքստում:
Ինչպիսի խնդիրներ են լինում բիզնեսում?.. Դիտենք օրինակ Վասիլի՝ ծրագրավորման վարչության ղեկավարի:
- «Նիկոլայ, այս խնդրի համար պարաչ կա այսօր!»
Նմանապես, հաղորդագրությունը կարող է կատարվել որոշ խնդրի համատեքստում գրքում. - «Կոլյա, գժվում ես երեկոյան Dota-ով»
Այդպիսով, նույնիսկ մեկ զրուցակիցների զույգի միջև շփումը կարող է միանգամից լինել ոստիկանական տարբեր թեմաների շուրջ. - «Պետր, Նիկոլայ, նայեք կցվածներում նոր սերվերի գինը»
Այդպես, մեկ հաղորդագրություն կունենա բազմաթիվ ընդունողներ. Այդ դեպքում հաղորդագրությունը կարող է պարունակել կցված ֆայլեր. - «Սեմեն, և դու էլ նայիր»
Եվ անհրաժեշտ է, որ արդեն գոյություն ունեցող զրույցին նոր մասնակիցը հրավիրվի.
Թույլ տվեք դադարեցնել այս «արդիական» պահանջների ցուցակը:
Իրական հայտի և նրան պահանջվող սահմանափակումների ըմբռնելիս, արդյունավետ տվյալների բազայի սխեմա նախագծելը գործնականորեն անհնար է:
Քայլ 2: Կղզիային տրամաբանական սխեմա
Սխեմականորեն առայժմ ամեն ինչ նման է էլեկտրոնային հաղորդագրությանը՝ առկա գործիքի ստանդարտ գործիքը: Այո, «ալգորիթմիկորեն» բիզնեսի բազմաթիվ խնդիրները նման են միմյանց, ուստի դրանց լուծման գործիքները կառուցվածքային առումով նման կլինեն:
Նայենք արդեն ստացված տրամաբանական հարաբերությունների սխեմային: Օգնելու համար մեր մոդելը օգտագործենք ամենահիմնական տարբերակը ցուցադրման առանց UML կամ IDEF նոտացիաների բարդեցման:

Մեր օրինակով, մարմինը, փաստաթուղթը և բինարային «միավորում» են այս «արտաքին» գոյությունները, որոնք ինքնուրույն գոյություն ունեն և առանց մեր ծառայության: Ուստի, պարզապես ու ճանաչելու ենք նրանց իբրև որոշակի սոդեր «որտեղ-որ» թողնել UUID-ով:
Նկարեք սխեմաները հնարավորինս պարզ — մեծամասնությունը, ում դուք դրանք ցույց եք տալիս, չեն գիտակցում UML/IDEF-ի ընթերցում: Բայց — նա նկարեք պարտադիր:
Քայլ 3: Խոր-րդ կառուցվածքը
Սեղանի անունների ու դաշտերի մասինԴա, թե ինչպես ենք վերաբերվում «ռուհեր» տեսակի դաշտերին ու աղյուսակներին, կարող է տարբեր կերպ ընկալվել, բայց դա՝ առարկայի խնդիրը: Որպեսզի ոչ մի օտար ծրագրավորող չկա, իսկ PostgreSQL-ն մեզ թույլ է տալիս անվանել թե թերագծերով, եթե դրանք ճանապարհված են մեջբերումներում, ուստի մենք նախընտրում ենք կոչել օբյեկտները պարզ ու հասկանալի, որպեսզի տարբեր մեկնություններ չառաջանան:
Որպեսզի հաղորդագրությունները մենք շատ մարդիկ միանգամից գրում են, մասամբ էլ նրանք կարող են անել դա օֆլայն ռեժիմում, ապա ամենադժվարագույն տարբերակը՝ ուրագործել UUID որպես ID-ներ ոչ միայն արտաքին էությունը, այլ նաև բոլոր օբյեկտները մեր ծառայության մեջ: Причем генерировать их можно даже на клиентской стороне — это поможет нам поддержать отправку сообщений при кратковременной недоступности БД, а вероятность коллизии крайне мала.
Մեր տվյալների բազայի նախնական կառուցվածքը կունենա այսպիսի տեսք՝
Աղյուսակներ : 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՝ Որոնել ոչ ակնհայտ պահանջները
Վերջապես, մենք նախագծեցինք տվյալների բազան, որի մեջ կարելի է շատ լավ գրել և ինչ-որ ձևով կարդալ:
Եկեք մեզ դնենք մեր ծառայության օգտվողի տեղը՝ ինչ ենք ուզում անել նրա միջոցով
- Վերջին հաղորդագրություններ
Սա հրապարակված կարգով ոլորտային տարբեր նշաններով «իմ» հաղորդագրությունները: Երբ ես հասցեատեր եմ, երբ հեղինակ եմ, երբ ինձ գրել են, և ես չեմ պատասխանել, երբ ինձ չեն պատասխանել, ... - Ուղարկման մասնակիցներ
Ո quiénParticipa en este largo largo chat, en realidad?
Մեր կառուցվածքն օգնում է լուծել այս երկու խնդիրները «ընդհանուր», բայց արագ՝ ոչ: Проблема в том, что для сортировки в рамках первой задачи անհնար է ստեղծել ինդեքս, որը համապատասխանում է յուրաքանչյուր մասնակցին (և ստիպված կլինենք ստանալ բոլոր գրառումները), իսկ երկրորդ համար անհրաժեշտ է ստանալ բոլոր հաղորդագրությունները մի թեմա:
Անհաշտ օգտվողի խնդիրները կարող են կարմիր թողնել արտադրողականությունը:.
Քայլ 5՝ 合理的 денормալизация
Մեր երկու խնդիրներն ոգեշնչելու են հավելյալ աղյուսակներ, որոնցում մենք պրկելու ենք որոշ տվյալներ, անհրաժեշտ է կազմել համապատասխան ինդեքսներ մեր խնդրում:

Աղյուսակներ : 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)
);Իսկ这里我们应用了两个典型的方法, применяемых при создании вспомогательных таблиц:
- Ռեկորդների բազմապատկում
Մենք ձևավորում ենք մեկ սկզբնական հաղորդագրության հիման վրա մի քանի հետևանքային գրառումներ տարբեր ռեესტրերում տարբեր սեփականատերերի համար՝ ինչպես ուղարկողի, այնպես էլ_RECEIVER-ի համար: Բայց այժմ յուրաքանչյուր ռեեստր թողնում է ինդեքս՝ որովհետև սովորաբար մենք կցանկանայինք տեսնել միայն առաջին էջը: - Ռեկորդների уникալизация
Յուրաքանչյուր հաղորդագրություն ուղարկելու դեպքում կոնկրետ թեմայի շրջանակում բավարար է ստուգել, թե արդյոք արդյոք նման գրառում արդեն գոյություն ունի: Եթե ոչ՝ ավելացնենք այն մեր «լեքսիկոն»:
Հաջորդ մասում հոդվածը խոսելու է մեր տվյալների բազայի կառուցվածքում:
Ընտանիք: habr.com
