Տվյալների Բազաների դասակարգումները և դրանց հետ արվող հիմնական գործողությունները

Vachagan Mirzoian
20 min readMar 7, 2022

Ծրագրավորումն իրենից ներկայանցնում է տվյալների հետ կոնկրետ ալգորիթմով կատարվող աշխատանք։ Բայց նախ պետք է ինչ–որ մի ձև պահել այդ տվյալերը։ Դրանք պահվում են տվյալների բազայում։ Ինֆորմացիան ստանալու համար օգտագործվում են բազում որևէ «Query language»–ի սահմանած հարցումներ։ Այդ լեզուները կազմված են լինում տրամաբանորերն առանձնացված 5 կտորներից՝

1) Data Definition Language, Data Description Language (DDL) — CREATE, ALTER, DROP TRUNCATE,

2) Data Manipulation Language (DML) — INSERT, UPDATE, DELETE,

3) Data Control Language (DCL) — GRANT, REVOKE,

4) Transaction Control Language (TCL) — COMMIT, ROLLBACK

5) Data Query Language (DQL) — SELECT

Բազաների և դրանց կառավարման համակարգերի դասակարումների համար կան բազում սկզբուննքներ։ Ըստ բիզնես–գործունեության կարելի է առանձնացնել ամպային տեխնոլոգիաները և մեծ պահեստները, որոնք բիզնեսի կարիքների բավարարման համար են։

Ըստ տարածքային բաշխվածության առանձնացնում ենք բաշխված բազա, որի տվյալները կարող են լինել ֆիզիկապես իրարից մեկուսի, բայց իրարար հավասար սերվերներում, տվյալները, գտնվելով առանձին համակարգիչներում, մշակվում են տարբեր պրոցեսորներով, սերվերները փոխկապակցված են ինտերնեով։ Կարող են ընդհանուր «Data center»–ում՝ նույն ֆիզիկական հասցեում լինել, բայց ենթատարրերի աշխարհագրական դիրքից ամբող բազան 1 տրամաբանական միավոր` Cluster է։ Հատվածները համարժեք պահելու համար դրանց միջև պետք է լինի ինտենսիվ կապ, պատճենավորում՝ «Replication» և կրկնօրինակում՝ «Duplication» ապհովելու համար։ Բաշխված բազաները լինում են «Homogenous» կամ համասեռ և «Heterogenous» կամ տարասեռ։ Համասեռ համակարգերի դեպքում բոլոր սերվերներն օգտագործում են նույն «DBMS»–ները։

Կա նաև կենտրոնացված բազա, որն ամբողջությամբ գտնվում է 1 տեղում։ Այս տարբերակը հաճախ է հանդիպում «LAN» ցանցերի դեպքում, երբ սահմանափակ տարածք զբաղեցնող կազմակերպությունում օգտագործվում է կենտրոնական սերվեր, որում էլ գտնվում է բազան։ Ապակենտրոնացված համակարգում կան մի քանի կենտրոններ, և կենտրոնացված բազայի նման, ենթատարրերը կարող են տարբերվել իրենց իրավունքներով և կարևորությամբ։

Ծրագրային ճարտարապետության տեսանկյունից բազաները կարող են լինել կա՛մ դրանք օգտագործող ծրագրից՝ «Client»–ից առանձին ինքնուրույն համակարգեր, կա՛մ լինել ծրագրին ներկառուցված՝ «Embedded», կցվել և օգտագործվել գրադարանի կամ որևէ այլ պրոյեկտի ձևով, ինչպես SQLite–ը։ SQL Server Compact–ը աշխատում է տվյալների կոմպակտավորման՝ փոքր ծավալում ավելի շատ կոդ գրելու և կոմպրեսավորման՝ եղած կոդը սեղմելով ավելի քիչ ֆիզիկական հիշողություն զբաղեցնելու հիման վրա։

Արագագործության հասնելու համար նախագծված են զուգահեռությամբ աշխատող բազաներ, հատկապես մեծածավալ ինֆորմացիա մշակելու համար։

Բազայում գտնվող տվյալը կարող է լինել Կառուցված՝ «Structured» կամ Չկառուցված՝ «Unstructured», հնարավոր են միջանկյալ տեսակներ։ Կառուցված են այն տվյալները, որոնք ունեն «Data Model»։ Կան նաև Semi–structured տիպեր։

Ըստ տվյալների մոդելի կառուցվածության կամ չկառուցվածության, բազաները նույնպես ունենում են մոդելներ՝ հարաբերական և ոչ հարաբերական, կան նաև բազաներ, որ աշխատում են 1–ից ավելի մոդելներով։ Հարաբերական բազաների դասական օրինակը SQL–ն է։ Ոչ հարաբերական բազաներ են բանալի–արժեք զույգերը, ընդլայնված սյունը, փաստաթղթայինը, որոշ գրաֆային բազաներ և այլն: Որոնաղական մոտեցումներով և բազմամոդել բաազաները ներառում են 2 խմբի հատկությունները։

Աղյուսակը ցույց է տալիս 5 ֆունդամենտալ մոդելների հատկանիշների համեմատությունը։

Relational կամ Հարաբերական տվյալների բազա — տվյալները պահվում են աղյուսակներում, որոնցում էլ տողերի և այուների հարաբերությամբ՝ Դեկարտյան արտադրյալով, կազմվում են համակցություններ կամ հարաբերություններ։

Ավելացնում ենք սյուն, հետո ջնջում ամբողջ սյունը, այսինքն՝ միայն 1 կոնկրետ վանդակ ջնել հնարավոր չէ։ Այս թերությունը շտկելու համար նախագծվել են սյունակենտրոն՝ Column–oriented բազաները։ Կարելի է համեմատել է դինամիկ և ստատիկ զանգվածներով արվող աշխատանքի հետ, երբ դինամիկ զանգվածի դեպքում երկարությունը փոփոխվում է, իսկ ստատիկի դեպքում առավելագույնը կարելի է անպետք դաշտում «null» կամ 0–ներ գրել։ Հաւաբերական բազաներում չափազանց կարևոր է ղյուսակի նորմալիզացիան։ Օբյեկտին վերաբերող տվյալները, կախված տիպից, խմբավորվում են առանձին այղյուսակներում, այնպես, որ դրանցից յուաքանչյուրում գտնվեն միայն նույնատեսակ և համասեռ տվյալներ։ Ոչ հարաբերական բազայի դեպքում կոնկրետ օբյեկտն է իր բոլոր դաշտերով պահվում առանձին փաստաթղթում, այսինքն խառը տվյալներ գտնվում են մեկ տեղում։

Տվյալների հետ աշխատող լեզվի և սերվերի կառավարումն իրականացնող լեզվի միջև կապի հաամար օգտագործվում են «Object Relational Mapper»–ներ։ Այն աղյուսակների ունեցած հարաբաերությունները դարձնում է ծրգրավորման լեզուների մեծ մասի կողմից կիրառելի օբյեկտներ կամ կլասներ, թույլ տալով կտրվել աղյուսակների միջև եղած բազում խճճված կապերից։ SQL–ի և .NET–ի միջև կիրառվում է «Entity Framework», որը թույլ է տալիս .NET–ի որևէ լեզվով, օրինակ՝ C#–ով գրվող կոդով աշխատել անմիջապես բազայի և տվյալների հետ, բայց միևնույն ժամանակ կտրված մնալ բազայի շերտից։ Ուստի Entity Framework–ն ինտերֆեյս է, առանց որի ստիպված էինք օգտվել «ADO.NET»–ից, որ ենթադրում է SQL–ի ոճով կոդ գրել։

Աղյուսակը ցույց է տալիս կարևոր հասկացությունները և դրանց նշանակությունը։

Key–value pairs կամ Բանալի–արժեքային զույգ — տվյալները հանդիսանում են «Hash Table»–ով աշխատող «Associative array»–ի օբյեկտներ, «Dictionary»–ի տարրեր, այլ կերպ՝ տողեր, որոնցից յուրաքանչյուրն ինքն իրենով առանձին միավոր է։ Ի տարբերություն այլ բազաների, այս դեպքում դատարկ դաշտերը տեղապահներով չեն լրացվում, որի շնորհիվ հիշողությունը չի ծանրաբեռնվում։ Ոչ հարաբերական բազաների ամենապարզ ձևն ու գլխավոր աբստրակցիան է։ Շատ դրսևորումներ, օրինակ «Redis» լեզուն, աշխատում են «In-memory» սկզբունքով, այսինքն ինֆորմացիան տեղափոխվում է «Client» համակարգիչ։ Արդյունավետ է քեշավորման, իրական ժամանակում գործողությունների կատարման և այլնի համար։

Graph — հիմական ինֆորմացիան ոչ այնքան ստատիկ տվյալներն են, որքան, որ բազայի տարրեր միջև եղած կապերն ու հարաբերությունները, այլ կերպ ասած՝ աշխատում է «relationships-first» մոտեցմամբ։ Նախագծված է ուղորդված գրաֆների հիաման վրա, ուստի ունի գագաթներ՝ «Node»–եր, որոնք հանդիսանում են որևէ տիպի օբյեկտ և կարող են պարունակել դաշտեր, ունի կողեր, որոնք ցույց են տալիս գագաթների միջև կապերը, ունի հատկություններ, որոնք պահում են լրացուցիչ ինֆորմացիա։ Տիպիկ համակարգեր են «TigerGraph»–ը GSQL լեզվով և «Neo4j»–ն Cypher լեզվով, իսկ օրինակ՝ «ArangoDB»–ն գրաֆայինից բացի, աշխատում է նաև փաստաթղթային ու բանալի–արժեք զույգով։ Թույլ է տալիս խուսափել «Associative entity»–ներից, Join–ներից և Lookup table–ներից, որոնք կա առկա են հարաբերական բազաների դեպքում և առաջ են բերում լրացուցիչ սխեմաներ, կապեր և ավելի կոմպլեքս ճարտարապետություն։ Քանի որ գրաֆային բազաներում մեծ ուշադրություն է դարձվում հարաբերություններին, ապա այս մոտեցումն ամենահարմարն է բարդ կապերով իրար փոխկապակցված տվյալներ պահելու հարմար։ Նման խնդիր օրինակ է «Chain optimization», որը հանդիպում է արտադրական շղթաներում, երբ տարբեր մատակարարներից պետք է ստանալ տարբեր դետալներ ու ստանալ վերջնական արտադրանք, բնակնաբար լոգիստիկ խնդիրները կարելի է անվերջ բարելավել։ Կիրառվում է ինտերնետային անվտանգության ապահովման և բանկային քարտերի խարդախությունների կանխման համար, երբ պետք է վերլուծել իրար հաջորդող բազում գործարքներ և գտնել շեղումներ։ Սա կարող է պահանջել նաև մեքենայական ուսուցման տարրեր։

Document–oriented կամ Փաստաթղթային հիքով բազա — նախատեցված են ընդհանուր օգտագործման համար, ուստի նույն փաստաթղթում կարող են պահվել ոչ համասեռ տվյալներ, ինչն էլ նորմալիզացիայի խնդիրներ է առաջացնում։ Ոչ հարաբերական բազների հիմնական տիպն է ու բանալի–արժեք զույգով աշխատող բազաների ենթախումբ։ Հարաբերական բազայի տրամագծորեն հակառակ կոնցեպտն է։ Փաստաթղթային և մյուս ոչ հարաբերական բազաներն օգտագործում են «Object Document Mapping», բայց դա խանդրահարույց է, քանի որ ի տարբերություն հարաբերական բազաների, ոչ հարաբերականները չունեն ստանդարիզացիա, ամեն բազա իր յուրահատկությունն ունի ու ամեն մեկի համար սահմանափակ կիրառություն ունեցող «ODM» մշակելը տնտեսապես շահավետ չէ։ Փաստաթղթոււմ ինֆորմացին պահվում է JSON, XML կամ այլ ձևաչափով։ Բազայի տիրույթում փաստաթուղթը հասանելի է եզակի ինդեքսի կամ բանալու ձևով, ինչպես նաև մետատվյալների միջոցով։ Բազայի օրինակներ են MongoDB–ն ու RedisJSON–ը։

Wide Column կամ Ընդլայնված սյունով բազա — պիտանի ինֆորմացիան հենց ամբողջական սյունն է, ամեն սյուներն առանձին ֆայլեր են ու կարող են հիշողության մեջ առանձին գրանցվել։ Կոնկրետ տվյալ ստանալն արագ է տեղի ունենում, քանի որ սյունը պարունակում է նույն տիպի տվյալներ, որոնց սերիալիզացիան և դեսերիալիզացիան ավելի արագ են տեղի ունենում։ Առաջին հայացքից հարաբերական բազաներին շատ նման է թվում, բայց սյուները հեշտությամբ կարող են փոփոխվել։ Կարելի է ներկայացնել, որպես երկչափանի Բանալի–արժեքային զույգ։

Կան սյուների վրա հիմնաված բազաների տարբեր իմպլեմենտացիաներ, որոնցից ամեն մեկի կոնտեքստում տողի կամ սյան առաջնայինությունը տարբեր է, այսինքն՝ բազայում, սյունից բացի, տողը նույնպես կարող է դեր ունենալ։ Կամ հենց բազան կառավաող համակարգը՝ «DBMS»–ը կարող է կարևոր լինել, օրինակ՝ «Column–oriented» բազաներում։ «Super column»–ի դեպքում սյան ամեն տարրը՝ տողը, նույնպես կարող է լինել բաղադրյալ և պարունակել 1–ից ավել ենթատարրեր։ Նկարում պատկերված է, թե ինչպես են աղյուսակում ստեղծվում տրամաբանակական այլ ենթաաղյուսակներ։

Մասնավոր դեպք է «JSON»–ը, որն իր մեջ պարունակում է օբյեկտ, որն ունենում է ենթաօբյեկտներ, դրանք էլ ունեն իրենց ենթաօբյեկտները և այլն։

Ծառի տեսքին նայելիս՝ տեսնում ենք ենթադաշտերի առկայությունը՝

Ամբողջ բազան հանդիսանում է մեկ «Keyspace»։

Ակնառու դրսևորումներ են ժամանակագրական հաջորդականությամբ ստացվող և պահվով տվյալները, օրինակ՝ ջերմաստիճանը, սեյսմիկ ակտիվությունը, կենսաչափական տվյալները և այլ պարբերական իրադարձությունները։ Օրինակ՝ ամսվա ինչ–որ օր հանդիսանում է բանալի, իսկ սեյսմիկ ակտիվության վերաբերյալ տվյալները զբաղեցնում են ամբողջ տողը։ Տեխնոլոգիաներ են CQL լեզուն, Apache HBase–ը և ScyllaDB–ն։

Search Engine կամ Որոնաղական համակարգերի բազա — նախատեսված է մեծածավալ տվյալների հետ գրեթե իրական ժամանակում աշխատելու համար։ Հայտնի տեխնոլոգիաներից են Solr–ը և Elasticsearch–ը։ Elasticsearch–ը տրամադրում է REST API–ներ և օգտագործում է անսխեմա JSON ֆորմատով փաստաթղփեր։ Ծայրակետերի միջև հարցումներն իրականացվում են HTTP բայերով՝ GET POST, PUT կամ PATCH և DELETE։ Փաստաթղթերը գտնվում են տարբեր սերվերների վրա, ուստի հարցումներն աշխատում են զուգահեռությամբ։ Բազայում նախապես իրականացվում է ինդեքսավորում, որի հիման վրա հաջորդ քայլով տվյալ ստանալն ավելի արագ է տեղի ունենում։

Multi model կամ Բազմամոդել — համադրում է հարաբերական և ոչ հարաբերական բազաների սկզբուքները։ Բազայի օրինակ է «Fauna» API–ը, որը հիմնականում գործում է «GraphQL»–ի հետ համադրված, բայց բազում ծրագրավորման լեզուներ ևս կարող են «Fauna»–ն օգտագործել սեփական հարցումների համար։ Համեմատաբար քիչ է կիրառվող JSON–ը, իսկ պատճենավորում՝ «Replication» չի պահանջվում։

Բազաների կոնցեպտների իրականացման ժամանակ ունենում ենք 2 հիմնական մոդել՝ հարաբերական և ոչ հարաբերական։

Բազաների հետ աշխատելիս գործ ենք ունենում մի շարք հասկացությունների հետ, օրինակ՝

1. Database՝ Տվյալների բազա

2. Cloud,

3. Data Warehouse և Data Lake,

4. OLAP և OLTP,

5. Quantitative` Քանակական և Qualitative՝ Որակական տվյալներ,

6. Data model, Database model

7. Structurized և Unstructured տվյալներ,

8. Replication և Duplication,

9. Functional Dependency, Partial Dependency, Transitive Dependency

10. Key՝ բանալիներ,

11. Normalization, Normal Forms,

12. Partitioning՝ մասնատում և Sharding՝ շերտավորում,

13.CRUD,

14. Indexing,

15. View,

16. Union, Intersect, Except

17. Transaction,

18. Stored Procedures

19. JOIN

20. Triggers

21. Schema

1. Database կամ Տվյալների բազա — տվյալների պահպանման աբստրակտ միջավայր, որը հաճախ զբաղեցնում է իրական հիշողություն՝ սարքավորում, բնականաբար ամեն իրավիճակի համար կան կոնկրետ մոդիֆիկացիաներ։

2. Cloud — հեռավար սերվերային համակարգ և բազա՝ բիզնես գործունեության համար։

3. Data Warehouse — կենտրոնացված համակարգ՝ բիզնես բանականության և գիտահեն վերլուծությունների համար։ Ի վիճակի են մշակել պետաբայթերի հասնող ինֆորմացիա, ի տարբերություն դասական բազաների, տեխնիկական ապահովման համար պետք են սուպեր համակարգիչներ։ Տեսականորեն օգտագործում է «Structured Data» և «Semi–structured Data», հետևաբար ունի նորմալիզացիա և տվյալների մաքրություն ու եզակիություն։ Ունի եռաշերտ ճարտարապետություն՝

1) Ստորին շերտ — կազմված է հիմանկան սերվերից, որը սովորաբար հարաբերական բազա է, իրականացնում է ETL կամ ELT պրոցես

2) Միջին շերտ — կազմած է OLAP կամ «Online analytical processing» շերտից, որն արագացնում է հարցումները,

3) Վերին շերտ — հանդիսանում է Front end կամ նմանատիպ այլ ինտերֆեյս

Ի մի է բերում տրանզակցիա իրականացնող համակարգերի` CRM կամ «customer relationship management», HRM «human resources management» և ERP «enterprise resource planning», իրական ժամանակում տվյալներ մշակող օպերատիվ բազաների, անգամ ոչ հարաբերական բազաների՝ հարթ ֆայլեր և այլ աղբյուրների կողմից ստացվող ինֆորմացիաները։ Վերջնական օգտագործման համար հասանելի է որպես ծրագրային ապահովում, ամպային տեխնոլոգիա կամ սարքավորում։

Պայմանականորեն կարելի է համեմատել «Stack»–ի հետ, երբ կա կանոնակարգ։

Data Lake — ընդհանուր նշանակության համակարգ, երկուական ֆայլային օբյեկտների համար, ինչպիսիք են նկարները, վիդեոները կամ աուդիոները, «Unstructured» տվյալներ պահելն է արդյունավետ, օգտագործում է ոչ հարաբերական բազաների համար, բայց կարող է պահել մոդել ունեցող տվյլաներ էլ։ Աչքաթող անելու և թերի կառավարելու դեպքում վերածվում է «Data Swamp»–ի։ Կարելի է համեմատել «Heap»–ի կոնցեպտի հետ։

Աղյուսակում համեմատվում են «Data Warehouse»–ը և «Data Lake–ը։

4. OLAP կամ Online Analytical Processing — Data Warehouse–ում պահվող արժեքների բազմաչափ վելուծություն։ Չափումներ են տեղադրությունը, առարկայի տեսակը, ժմանակը և այլն։ Քանի որ օգտագործում է հարաբերական բազաներ, որոնցում միայն 2 չափում է, աղյուսակները համադրվում են և ստեղծում բազմաչափ ֆորմատով տվյալներ՝ խորանարդներ։ Հարցումները բարդ են և ներառում են մեծաքանակ տողեր։ Չեն փոփոխում առկա տվյալները, քանի որ մեծամասամբ միայն կարդում են դրանք։

OLTP կամ Online Tansactional Processing — մեծածավալ տրանզակցիաների մշակում։ Ապահովում է, որ նույն ինֆորմացիան շատերի կողմից օգտագործվի, ինդեքսավորում է տվյալները։ Հարցումները պարզ են և ներառում են մի քանի տող։ Տվյալների փոփոխությունն արագ է ընթանում։ Լավ օրինակ են օնլայն վճարային համակարգերը։

5. Քանակական տվյալներ — միայն իրենց գոյությամբ արդեն ունեն օբյեկտիվ բնութագիր, նկարագրվում են վիճակագրական հանտկանիշերով՝ քանակաով, արժեքով, չափով և այլն։ Լինում են դիսկրետ կամ անընդհատ։ Համընկնում են Structured տվյալների հետ։

Որակական տվյալներ — որևէ հատկանիշով կամ ատրիբուտով միավորված տվյալներ։ Քանի որ միավորումը սուբյեկտիվ երևույթ է ու կարող է շատ այլ ձևերով էլ իրականացվել, որակական տվյալները չկառուցված կամ կիսակառուցված են, այսինքն՝ կա հետագա հստակացման և դասակարգման կարիքու հնարավորություն։ Համընկնում են Unstructured տվյալների հետ։

6. Data Model — ստացվում է մոդելավորմամբ, տվյալներին տալիս է իմաստային կառուցվածք, սահմանում իրար հետ հարաբերվելը և իրական աշխարհի օբյեկտների հատկությունների հետ ունեցած նմանությունը։

Database Model — սահմանում է տվյալների բազայի տրամաբանական կառուցվածքը։ Մոդելներ են ցանցայինը, փաստաթղթայինը, հարաբերականը, օբյետտ–ատրիբուտ–սյունը և այլն։

7. Structured Data — քանակական տվյալներ, որ կազմված են թվերից և արժեքից, ներկայացվում են աղյուսակների տեսքով, ունեն նախասահմանված մոդելներ, պահվում են Data Warehouse–ներում, հարցումներն արվում են SQL–ական լեզվով։ Դեռևս չմշակված նախնական տվյալներին կառուցվածք՝ «Structure» կարելի է հաղորդել անգամ HTML լեզվով նշագրելու միջոցով։ Կարելի է կայքն օպտիմիզանցել որոնողական համակարգի կողմից ավելի նկատելի դառնալու համար։

Unstructured Data — որակական տվյալեր, տվյալների նախնական վիճակը, երբ բացակայում է Data model–ը, և ըստ այդմ մեծ քանակներ ստանալը հեշտ է, ինչն էլ պահանջում է մեծ հիշողություն։ Քանի որ կարող է ադապտացվել տարբեր ֆայլային ֆորմատների, կարելի է վերասահմանել կոնկրետ կարիքների համար և հասնել ռեսուրսների արդյունավետ օգտագործման։ Use case–եր են Data mining–ը, NLP–ը և կանխատեսումային վերլուծությունները, ավելի արդյունավետ պահվում են Cloud Data lake–երում, մշակվում են NoSQL համակարգերում։

Կարճ՝ բազայում գտնվող տվյալը կարող է լինել Կառուցված՝ «Structured» կամ Չկառուցված՝ «Unstructured», հնարավոր են միջանկյալ տեսակներ։ Կառուցված են այն տվյալները, որոնք ունեն «Data Model», որը ստացվում է մոդելավորմամբ, այսինքն՝ տվյալներին տալիս է իմաստային կառուցվածք, սահմանում իրար հետ հարաբերվելը և իրական աշխարհի օբյեկտների հատկությունների հետ ունեցած նմանությունը։ Կան նաև Semi–structured տիպեր։

8. Replication — հատուկ ծրագիրը գտնում է բազայի տարբեր կտորներում արված փոփոխությունները և անում այնպես, բոլոր կտորները նույն տեսքն ունենան, այսինքն՝ կա՛մ չեղարկում է փոփոխությունը, կա՛մ մյուս կտորների վրա տարածում այդ փոփոխությունը։

Duplication — ընտվրում է 1 գլխավոր բազա և կրկնօրինակվում դրա պարունակությունը, հետագա փոփոխություններն արվում են այդ 1 բազայի հետ։ Նույն «Backup»–ն է։

9. Functional Dependency — սահմանափակող հարկադրություն, գրվում է «X→Y», որտեղ «X»–ը միանշանակորեն ասոցացված է «Y»–ի հետ։ Օրինակ՝ Ավտոմեքենայի նույնականացման համարը՝ «VIN»–ը, ասոցացված է շարժիչի հզորությանը, գրվում է «VIN→Engine», քանի որ կոնկրետ մեքենան ունի միայն 1 հզորություն։ «Engine→VIN» գրառումը սխալ է, քանի որ նույն հզորությամբ շատ մեքենաներ կան։ Աղյուսակում ուսանողը կարող է մեկից ավելի դասընթացների գրանցվել և ունենալ կամայական թվով կիսամկայային մասնակցություն։

Երբ աղյուսակում 2 տող ունենում են նույն «Student ID»–ին, ապա նրանք նաև ունենում են նաև նույն «Semester» արժեքը։ Այստեղ ունենք «StudentID → Semester» ֆունկցիոնալ կախվածություն։ Կախվածության այլ օրինակ է «{StudentID, Lecture} → {TA, Semester}» հարաբերությունը, երբ ունենք նախապես ընտրված {StudentID, Lecture} ատրիբուտների բազմությունը և {TA, Semester} բազմությունը, որտեղ «{StudentID, Lecture}»–ը սուպեր բանալի է։

Հետևյալ օրինակում յուրաքանչյուր աշխատակից կարող է ունենալ միայն 1 «Department ID»։ Քանի որ ամեն մեկը կարող է աշխատել միայն մեկ վարչությունում, «Employee ID»–ին սահմանում է նաև վարչությունը՝ «Employee ID → Department ID»։

Employee ID»–ին սահմանում է նաև աշխատողի անունը՝ «Employee ID → Employee Name»։ Աղյուսակում նաև ոչ բանալի ատրիբուտով կազմված ֆունկցիոնալ կախվածություն կա՝ «Department ID → Department Name»։ Չնայած կա «Employee ID → Department ID» ֆունկցիոնալ կախվածություն, «Employee ID»–ով «Department ID» ստանալը տրամաբանական չէ։

Partial Dependency — ի հայտ է գալիս, երբ ոչ բանալի սյունը ֆունկցիոնալ կախվածության մեջ է պոտենցիալ բանալի կազմող սյուներից որևէ մեկից։

Դիտարկենք օրինակը՝

Առաջնային բանալին կազմված է «StudentID» և «ProjectNo» սյուներից։ «StudentName» և «ProjectName» սյուները պիտի կախված լինեն առաջնային բանալուց։ «StudentName»–ը կարող է որոշվել «StudentID»–ով, «ProjectName»–ը կարող է որոշվել է «ProjectNo»–ով։ Ուստի ունենք մասնավոր կախվածություն։ Սա խախտում է նաև 2–րդ նորմալ ձևի կանոնները։

Transitive dependency — ֆունկցիանալ կախվածության տեսակ, երբ 1–ին սյունը կապված է 3–ին 2–ի միջոցով։ Աղյուսակում նման օրինակ է՝

Եթե գիտենք գիրքը, ապա գիտենք նաև հեղինակի ազգությունը՝ «{Book}→{Author nationality}», քանի որ գրքով նախ գտնում ենք հեղինակին՝ «{Book} → {Author}», իսկ հեղինակով էլ՝ հեղինակի ազգությունը՝ «{Author}→{Author nationality}»։ Ոչ բանալի ատրիբուտը սահմանում է մեկ այլ, ոչ բանալի ատրիբուտ։

10. Բանալի ատրիբուտ կամ սյուն, որը թույլ է տալի նույնականացնել տողը։ Կան խմբեր՝

1) Super Key — ատրիբուտների բազմություն, որը եզակիորեն նույնականացնում է յուրաքանչյուր տողը, չունի նվազագույն չափ ունենալու պահանջներ, ուստի կարող են ներառել ավելի կոմպակտ այլ բանալիներ։ Սահմանում է ֆունկցիոնալ կախվածություն։

2) Candidate key — նվազագույն չափ ունեցող «Super Key»։ Սրա կազմի մեջ մտնող սյուները կոչվում են «Prime Attribute», չմտնողները՝ «Non–Prime attribute»: «NULL» արժեք չպարունակող աղյուսակն ունի ամենաքիչը 1 «Candidate key»։ Հանդիսանում է տողն իդենտիֆիկացնելու հնարավոր բոլոր կոմբինացիաները։

3) Primary Key — ատրիբունտների նվազագույն բազմությամբ կազմած ընտրություն, որը եզակիորեն սահմանում է տողը։ «Candidate key»–ի մասնավոր դեպք է։ Առավելագույնը կարող է լինել առավելագույնը 16 սյուն և 900 բայթ։

4) Foreign key — սյուների բազմություն, որը կազմված է այլ աղյուսակի առաջնային բանալուց։ «Foreign Key» պարունակող աղյուսակը կոչվում է երեխա կամ ժառանգ աղյուսակ, իսկ առաջնային բանալի պաունակողը՝ ծնող։ Երեխա աղյուսակում գրվող արտաքին բանաին կա՛մ հավասր է այլ աղյուսակի առաջնային բանալուն, կա՛մ ունենում է NULL արժեք։ Սա կոչվում է «Referential integrity»։

5) Simple key — միայն մեկ ատրիբուտից՝ սյունից կազմբած բանալի:

6) Concatenated key — կազմված 2 կամ ավել սյուներից:

7) Compound key — կազմված 2 կամ ավելի սյունից, որոնք այլ աղյուսակի ցույց տվող առաջնային բանալի են։

8) Composite key — առաջնային բանալու մասնավոր դեպք, կազմված 2 կամ ավելի սյունից, որոնցից գոնե 1–ը պարզ բանալի չէ։ Դիտարկենք աղյուսակը՝

Միայն 1 դաշտով հնարավոր չէ եզակի արժեք ստանալ, քանի որ ամեն սյան մեջ կան կրկնվող արժեքներ։ «Team» և «Squad number» սյուների արժեքները համադրելով ստեղծվում է Առաջնային բանալի։

9) Natural key — եզակի ինդենտիֆիկատոր, որը նաև իրական աշխարհի օբյեկտի հետ է համընկնում, ունի բիզնես նշանակություն։

10) Surrogate key — եզակի ինդենտիֆիկատոր, որն իրնքն իրենով էլ արժեք է, ավելի շատ առնչվում է տվյալների տրամաբանական կառուցվածքին՝ «Data Model»–ին, քան հիշողության ֆիզիկական կառաուցվածքին՝ «Storage model»–ին։ Կոնկրետ բազայի տիրույթում կարող է հանդես գալ որպես առաջնային բանալի։ Բազայում թեստային արժեքների գրանցման ժամանակ ավտոգեներացվող արժեքով բանալի է։

11. Նորմալացում — նորմալ ձևերի օգտագործմամբ հարաբերական բազաները կառուցելու գործընթաց, տվյալների կրկնությունների նվազեցման և տվյալների ամբողջականության բարձրացման համար։ Սյուները և աղյուսակները կազմակերպվում են այնպես, որ կախվածություններն իրականացվեն ըստ բազաների ամբողջականության սահմանափակումների։ Իրականացվում է կա՛մ բազաների սինթեզով, կա՛մ դեկոմպոզիցիայով, այսինքն՝ աղյուակների նոր հիերախիաներ կառուցելով կամ քանդելով։ Նորմալ տեսքի բերելը կարող է արագագործության վրա նաև բացասական ազդեցություն ունենալ, դժվարեցնել հարցումներ գրելը և այլն, ու կարող է դենորմալիզացիայի կարիք առաջանալ։ Հասկացությունը կիրառվում է միայն հարաբերական բազաների համար, չնայած, որ ոչ հարաբերական բազաները նույնպես կարելի է կատարելագործել։

Նորմալ Ձևեր — նորմալացման համար օգտագործվող ռազմավարությունները, յուրաքանչյուր հաջորդ մակարդակ բավարարում է նախորդ մակարդակին էլ։

1–ին նորմալ ձև — յուրաքանչյուր վանդակ պիտի ունենա եզակի արժեք, ներդրված արժեքներ թույլատրված չեն։ Կոնկրետ Id ունեցող տողի որևէ վանդակում 1–ից ավելի արժեքներ պահելու փոխարեն, պետք է դրանք գրել առանձին վանդակներում՝ օգտագործելով այդ նույն Id–ին։

Դիտարկենք սխալ աղյուսակի օրինակ՝

1–ին նորմալ ձևի բելելուց հետո ունենում ենք հետևյալ տեսքը՝

2–րդ նորմալ ձև — չկա «non-prime attribute», որը պոտենցիալ բանալիների որևէ ենթաբազմության հետ ֆունկցիանալ կախվածության մեջ է։ Այսինքն՝ առաջնային սյուն չհանդիսացող այլ սյուները, առաջնային բանալու թեկնածու սյուներից ֆունկցիոնալ կախվածության մեջ չպիտի լինեն։ 1 սյունանոց առաջնային բանալով աղյուսակը միշտ 2–րդ նորմալ ձևի է։ 2–րդ ձևի դառնալուց առաջ աղյուսակը նախ պիտի լինի 1–ին նորմալ ձևի։

Այս աղյուսակի հավանական առաջնային բանալին բաղադրյալ է՝ կազմված «Manufacturer» և «Model» սյուներից։ «Manufacturer country» սյունը չի հանդիսանում առաջնային բանալի, անգամ չի էլ կարող դիտարկվել որպես այդպիսին և կախված է «Manufacturer»–ից։ Սա 2–րդ նորմալ ձևի պայմանների խախտում է։ Պայմաններին բավարարելու համար պետք է ունենալ 2 աղյուսակ՝

Մասնակի կախվածություն պարունակող աղյուսակը՝

2–րդ նորմալ ձևի բերելու համար այն տարանջատում ենք մասերի ՝

Հետևյալ օրինակում նույնպես խախտված է 2–րդ նորմալ ձևը՝

Առաջնային բանալին կազմված է «PART» և «WAREHOUSE» սյուներից, բայց «WAREHOUSE_ADDRESS» սյունը կախված է միայն «WAREHOUSE» սյունից։ Նույն պահեստը տարբեր տողերում կարող է ունենալ տարբեր հասցեներ։ Պետք է այնպես անել, որ 1 պահեստը միշտ 1 մեկ հասցե ունենա, այսինքն՝ պահեստը պիտի օգտագործվի որպես առաջնային բանալի, գրվի առանձին աղյուսակում։

3–րդ նորմալ ձև — պիտի բանալու կազմի մեջ չմտնող սյուները կախված չլինեն բանալու կազմի մեջ չմտնող սյուներից և կախված լինեն միայն բանալի սյունից։ Սահմանում է կրկնօրինակումների նվազեցումը, հեշտացնում տվյալների կառավարումը և «Referential integrity»–ին։ Այս աղյուսակն արդեն 2–րդ ձևի է, բայց չի համապատասխանում 3–րդ նորմալ ձևին։

Մրցույթը և անցկացման տարին՝ {Tournament, Year}–ը, բավական են տողը միանշանակորեն որոշելու համար, հանդիսանում են առաջնային բանալի։ Բայց խնդիրն այն է, որ «Ծննդյան ամսաթիվ» ոչ բանալի սյունը «Հաղթող» միջնորդ սյունով է կախված առաջնային բանալուց և նույն մարդը կարող է տարբեր ծննդյան ամսաթվերով հանդես գալ։ Աղյուսակը մասերի բաժանոլով՝ լուծում ենք խնդիրը։ «Հաղթող» սյունը բանալի է, որին արդեն միայն 1 արժեք է համապատասխնում։

Boyce–Code կամ 3․5 Normal Form — 3–րդ նորմալ ձևում գտնվող աղյուսակ, որում չկան համընկնող թեկնածու բանալիներ։ Կա A → B կախվածությունը, որտեղ «A»–ն սուպեր բանալի է, այսինքն մյուս սյունակները, օրինակ «B»–ն որոշվում, գտնվում են սուպեր բանալիով։ Պիտի լինի միայն է առաջնային բանալի։

4–րդ նորմալ ձև — աղյուսակը չի պարունակում 2 կամ ավելի անկախ, բազմարժեք տվյալներ։ Կա 2 կապ՝ «Աշխատակից և կարողություն» և «Աշխատակից և լեզվի իմացություն»։ Չի կարելի ունենալ «Skill Code և Language Proficiency» և «Language Code և Skill Proficiency» հարաբերույուններ, դրանք իրար հետ կապ չունեն։

Նման աղյուսակը տվյալներով լցնելու դեպքում «Null» արժեքներ ենք գրելու։

Շտկելու համար գրում ենք հետևյալը և «Null» գրելու կարիք չի լինի։

5–րդ նորմալ ձև — բաղադրյալ բանալին չի պարունակում ցիկլային կախվածություններ։

12. Partitioning — ինչ–որ սկզբունքով ինքնուրույն միավորվերի բաժանում։ Հարաբերական բազայում կա 2 ձև՝ հորիզոնական և ուղահայաց։ Ուղահայաց մասնատման օրինակ է նորմալիզացիան, երբ 1 աղյուսակում 5 սյուն ունենալու փոխարեն ունենում ենք 2 կամ ավելի աղյուսակներ, որոնք ունենում են 5–ից պակաս սյուներ։ Հորիզոնական բաժանումը կոչվում է «Sharding»։ Դիտարկենք նկարը՝

Sharding — հորիզոնական շերտավորում, այնպես, որ նոր ստացվող կտորները պահեն բազայի սխեման և սյուները։ Աղյուսակը կամ փաստաթուղը մասնատվում է, քանի որ մեծ կտորի հետ աշխատելը դժվար է, իսկ փոքր կտորները կարող են տարբեր բազաներում կամ սերվերում պահվել և տարբեր պրոցեսորներով զուգահեռ մշակվել։ Բարելավում է ինդեքսավորումն ու որոնումը։ Բաժանման և տրանզակցիայի համար կարևոր է «Sharding Key»–ին։ Նույն բանալին ունեցող տարրերը դառնում են անբաժանելի միավոր, փոփոխվում են միասնաբար, կազմում են տրամաբանական միավոր՝ «Logical Shard»։

13. CRUD — բազան կառավարելու տարրական «Create», «Read», «Update» և «Delete» գործողություններ։

«CREATE» հրամանով ստեղծում ենք բազա և աղյուսակներ, «INSERT» հրամանով ներմուծում ենք տվյալներ, հետո կարդում՝

Գրքերրի աղյուսակը պարունակում է ID, վերնագիր, ISBM, հեղինակների և հրատարակչի անուններ։ Ոչ բոլոր գրքերն ունեն 2 հեղինակ և հրատարակիչ:

Հետևյալ կոդի առաջին հատվածը «USER» աղյուսակում հայրանունների համար ավելացնում է նոր սյուն և փոխում լռելյան NULL արժեքները, այնուհետև ջնջվում է այդ նույն սյունը։ Ջնջվում են այն տողերը, որոնք պարունակում են 2019 — ից առաջ կատարված գնումները։ Վերջում «DROP» համանով ջնջվում են աղյուսակը և բազան։

Սյուն ավելացնելիս ունենում ենք հետևյալ պատկերը՝

14. Indexing — տվյալներն ավելի արագ կարդացող հարցումների մշակում, նաև նոր սյուների ստեղծմում (1)։ Իմաստով մոտ են բանալիներին։ Ինչպես բանալին է հատկանիշ, որը բնութագրում է տվյալին, այնպել էլ ինդեքսն է լրացուցիչ հատկանիշ։ Պարզ է, որ այդ լրացուցից հատկանիշը պահելու համար կարող է մեծ հիշողություն պահանջվել։ Եթե գիտենք կոնկրետ տողի ինդեքսը, ապա կաշխատենք միանգամից այդ տեղի հետ, ամբողջ աղյուսակը վերցնելու կարիք չի լինի։ Հայտարարենք ինդեքս՝

Կոդի 1–ին հատվածում ստիպված ենք աղյուսակի բոլոր–բոլոր տողերը վեցնել, և ստուգել վերնագիրը։ 2–րդ հատվածում արագացնում ենք հարցման կատարումը։ Պետք է նշել, որ ինդեքսավորման առավելությունը երևում է մեծ աղյուցակների մեջ օգտագործելու դեպքում։

15. View — տրամաբանական աղյուսակ, որը միայն ցուցադրում է տվյալներ, բայց ֆիզիկապես հիշողության մեջ գրանցված չէ (2)։ Ստեղծենք «VIEW», որը կներառի C#–ի այն գրքերը, որոնք ունեն 2 հեղինակ, հետո կփոխենք, որպեսզի տեսնենք SQL–ի վերաբերյալ բոլոր գրքերը։

Կոդի առաջին մասի աշխատանքի արդյունքը՝

«VIEW»–ն փոփոխությունից հետո՝

16. UNION, EXCEPT և INTERSECT — տողերի համակցությունների կազմում (3)։

17. Transaction — 1 կամ ավել գործողությունների կոնտեքստ, աշխատանքային միավոր (4)։

Կեղծկոդով ալգորիթմը հետևյալն է՝

1. «BEGIN TRAN» — ով սկսել տրանզակցիա

2. Կատարել հարցումները, տվյալների փոփոխությունները

3. Եթե խնդիր չկա, գրել «Commit» և ավարտել

4. Եթե խնդիր կա, Rollback վերադառնալ նախնական վիճակին

Կա 3 կարգավիճակ՝

1. Explicit transaction — ուղղակիորեն սկսվում է «BEGIN TRANSACTION» հրամանով, ավորտվում «COMMIT TRANSACTION» կամ «ROLLBACK TRANSACTION» հրամանով։

2. Implicit transaction — նման է ակնհայտ տրազակցիային, աշխատում է «COMMIT TRANSACTION» և «ROLLBACK TRANSACTION» հրամաններով, բայց «SET IMPLICIT_TRANSACTIONS ON» հրամանով պետք է սկսել «թաքուն» տրանզակցի, որից հետո տրանզակցիայի օբյեկտները կարգելափակվեն, ինչպես «Lock»–ի դեպքում, շարունակում են մշակվել «Commit» և «Rollback» հրամանների կիրառմամբ։

3. Auto–commit transaction — ժամանակի առ ժամանակ կատարվող տրանզակցիա, որն ակնհայտ կամ ոչ ակնհայտ ձևով չի կատարվում։ «SELECT» և «INSERT» հրամաններն ավտոմատ տրանզակցիայի օրինակ են։ Չհամապատասխող տվյալներ ներմուծելու դեպքում «Rollback» տեղի է ունենում ավտոմատ կերպով, այսինքն՝ սխալի պատճառով տվյալների փոփոխություն տեղի չի ունենում։

Ցանկացած տրանզակցիա պիտի բավարարի 4 պայմանի՝ ACID

1. Atomic — բոլոր գործողություններն ատոմի նման անբաժան միավոր են, կա՛մ միասնաբար կատարվում են, կա՛մ միասնաբար ձախողվում։

2. Consistent — արդյունքը կանխատեսելի է, տրանզակիցային առաջ և հետո բազան մնում է կայուն, անսխալ։

3. Isolated — ապահովում է, որ միաժամանակ նույն տվյալների հետ գործողություն կատարելու փոխարեն, տվյալները մշակվեն հաջորդաբար։

4. Durable — վերջնական արդյունքը կախված չէ կատարման ընթացքից։ Եթե կա տրանցակցիայի արդյունք, որի ստացումից հետո համակարգը խափանվել է, արդյունը չպիտի անհետանա։

Checkpoint — «Transaction log»–ում պահվող և տրանզակցիոն գործընթացի ընթացքում փոփոխվող տվյալները ֆիզիկական հիշողության մեջ գրանցելը։ Նախ «Log» ֆայլերը գրանցվում են հիշողության մեջ, բուֆերային քեշից հում տվյալներն են գնում հիշողություն, Checkpoint Log Sequence Number–ը գրվում են «Boot page»–ում։ Կա 4 տեսակ՝ «Automatic», «Indirect», «Manual» և «Internal»։ Տրանզակցիայի արած ամեն փոփոխություն բուֆերային ավազանից անմիջապես չի տեղափոխվում հիշողություն, այլ կատարվում է «Checkpoint»– սահմանած սկզբունքով։

T–SQL ում DDL հարցումների մեծ մասը տրանզակցիոնալ է (5)։

18. Stored Procedures ընթացակարգ, բազայում պահվող օբյեկտ, կարող է ընդունել պարամետրեր, կարող է և վերադարձնել (6)։

19. Join — 2 կամ ավելի աղյուսակներից սյուներ ընտրելու գործիք (7)։ Կան բազում մաթեմատիկակական մոդելներ, բայց T–SQL–ում կա 5 տրամաբանական տեսակ՝ «Inner Join», «Left Outer», «Join Right», «Outer Join», «Full Outer Join» և «Cross Join»։ Հիմանական տեսքը՝

SELECT

FROM Table A

JOIN Table B

ON …

WHERE …

Նախ ստեղծենք աղյուսակներ, որոնցում կպահվեն գնորդի, գնված ապրանքի և գործարքի տվյալները՝

«INSERT INTO» հրամանով լցնելուց հետո «SELECT»–ով ստանում ենք Գնորդ, Ապրանք և Գործարք աղյուսակները՝

Գործարքների աղյուսակից օգտվելով, կարող ենք պարցել, թե ով ինչ է գնել։

Գնորդի աղյուսակից վերցնում ենք անունը, ազգանունը, քաղաքը։ Ապրանքների աղյուսակից ընտրում ենք ապրանքատեսակի անունը։ Բայց Գնորդի աղյուսակը պետք է միավորենք ապրանքի և գործարքների աղյուսակների հետ։ Արդյունքը դասավորվում է այբենական կարգով։

20. Triggers — որևէ իրադարձությունից՝ «Event»–ից հետո աշխատող «Stored Procedure» (8)։ «DML» Trigger–ները կոնկրետ «Event»–ներից՝ Insert–ից, Delete–ից և Update–ից հետո են աշխատում։ Նախապես կոմպիլյացվում են և աշխատել սկսում են ավտոմատ։

Հայտարարվում է տրիգեռ, սահմանվում է իրադարձությունը, գրվում է մարմինը։

Պատվերների աղյուսակից ջնջվում են 16–ից մեծ ID ունեցող տողերը, բայց ջնջումն ակտիվացնում է 2 նոր պատվեր ավելացնող տրիգեռ։ ID սյունին նայելիս, համոզվում ենք, որ նախ ջնջվել են տողեր, հետո նորից ավելացել են։

Տրիգեռի մարմնի մեջ կարող ենք JOIN ստեղծել։

Հենց փորձենք «INSERT» անել, ստանելու ենք «JOIN was done instead of INSERT» հայտարարությունը, և հայտարարված JOIN–ի աղյուսակը։

21․ Schema — աղյուսակի կամ հարաբերության և դրա տարրերի՝ ատրիբուտների բազմության ամբողջությունը։ Այն սահմանվում է ծրագրավորման լեզվով գրված կոդով՝ DDL–ով (9), բայց այս հասկացությունն ավելի հաճախ նշանակում է գրաֆիկական պատկերումը։ Աղյուսակների աստղաձև սխեման հաճախ է կիրառվում դենորմալիզացիայի ժամանակ (10)։ Հանդիսանում է բազայում եղած աղյուսակների կամ այլ միավորների կապը, հիերարխիան և հատակագիծը։ Պահվում և նկարագրվում է բառարանում, որը մետատվյալի տեսք ունի է։

Տվյալների բազաների նախագծումը նախ և առաջ հիմնված է գիտական աշխատությունների և տեսական կոնցեպտների վրա։ Յուրաքանչյուր բիզնես կարող է առաջարկել այդ կոնցեպտների իրականացման և բազայի նախագծման իր ճարտարապետությունը՝ հաշվի առնելով շուկայի պահանջները։

Օգտագործված ռեսուրսները՝

1) Learn SQL Database Programming, Query and manipulate DBs from popular relational DB servers using SQL, Chapter 4

2) SQL Pocket Guide, A Guide to SQL Usage, 4th Ed., Chapter 5

3) T-SQL Querying, Developer Reference, Chapter 3

4) Beginning T-SQL with Microsoft SQL Server 2005 and 2008, Chapter 10

5) Exam Ref 70–761 Querying Data with Transact-SQL, Chapter 3.2

6) Microsoft SQL Server 2019, A Beginner’s Guide, 7th Ed. Chapter 8

7) Beginning T-SQL, A Step-by-Step Approach, 4th Ed. Chapter 5

8) Beginning T-SQL, A Step-by-Step Approach, 4th Ed. Chapter 5, Chapter 13

9) Learn SQL Database Programming, Query and manipulate DBs from popular relational DB servers using SQL, Chapter 1

10) Database Design and Relational Theory, Normal Forms and All That Jazz, 2nd Ed., Chapter 8

Data Lake vs Data Warehouse — https://www.talend.com/resources/data-lake-vs-data-warehouse/

Data lake և data warehouse — https://www.ibm.com/cloud/blog/cloud-data-lake-vs-data-warehouse-vs-data-mart

Որակական և Քանակական տվյալներ — https://www.g2.com/articles/qualitative-vs-quantitative-data

Structured and Unstructured data — https://www.ibm.com/cloud/blog/structured-vs-unstructured-data

Տրանզակցիաների տեսակները — https://www.sqlshack.com/modes-of-transactions-in-sql-server/

Հարցերի դեպքում գտեք ինձ LinkedIn–ում, Instagram–ում, TikTok–ում և Facebook–ում։

--

--