Karakteristikat e dizajnit të modelit të dhënash për NoSQL

Hyrje

Karakteristikat e dizajnit të modelit të dhënash për NoSQL «Duhet të vraposh me të gjitha forcat vetëm për të qëndruar në vend,
në mënyrë që të arrish diku, duhet të vraposh të paktën dy herë më shpejt!»
(s) Aliça nĂ« Vendin e Çudirave

Disa kohë më parë, më kërkuan të mbaja një ligjëratë për analistët e kompanisë sonë mbi projektimin e modeleve të dhënash, sepse duke qëndruar për një kohë të gjatë në projekte (ndonjëherë për disa vite) ne humbasim nga vëmendja atë që ndodh përreth në botën e teknologjive IT. Në kompaninë tonë (është njësoj) në shumë projekte nuk përdoren bazat e të dhënave NoSQL (të paktën deri tani), prandaj në ligjëratën time u dedikova veçanërisht atyre në shembullin e HBase dhe përpiqesha të orientoj materialin për ata që nuk kanë punuar kurrë me to. Në veçanti, ilustrova disa veçori të projektimit të modelit të dhënave mbi një shembull që kam lexuar disa vite më parë në artikullin «Introduction to HBase Schema Design» nga Amandeep Khurana. Duke shqyrtuar shembujt, krahasova disa mundësi zgjidhjeje për të njëjtën detyrë, për të sjellë më mirë idetë kryesore te dëgjuesit.

Së fundmi, «për shkak të mungesës së gjërave për të bërë», fillova të mendoj (fundjavat e gjata të majit në karantinë e nxisin këtë veçanërisht), sa do të përputhen konkluzionet teorike me praktiken? Në thelb, kështu lindi ideja e këtij artikulli. Një zhvillues që ka disa vite përvojë me NoSQL, ndoshta nuk do të nxjerrë diçka të re nga ajo (dhe prandaj mund të kalojë menjëherë disa etapa të artikullit). Por për analistët, që ende nuk kanë punuar ngushtë me NoSQL, mendoj se do të jetë e dobishme për të marrë konceptet bazë mbi veçoritë e projektimit të modeleve të dhënash për HBase.

Analiza e shembullit

Sipas mendimit tim, para se të filloni të përdorni bazat e të dhënave NoSQL, është e rëndësishme të mendoni mirë dhe të peshojnë "për" dhe "kundër". Shpesh, problemin mund ta zgjidhni edhe me sistemet tradicionale të menaxhimit të të dhënave relacionale. Prandaj, është më mirë të shmangni përdorimin e NoSQL pa arsye të forta. Nëse gjithsesi vendosni të përdorni një bazë të dhënash NoSQL, duhet të keni parasysh se qasjet në dizajn janë paksa të ndryshme. Sidomos, disa prej tyre mund të duken të panjohura për ata që deri tani kanë punuar vetëm me sistemet relacionale të menaxhimit të të dhënave (sipas vëzhgimeve të mia). Në "botën relacionale", zakonisht fillojmë me modelimin e fushës së aplikimit dhe më pas, kur nevojitet, realizojmë denormalizimin e modelit. Ndërsa në NoSQL ne duhet menjëherë të marrim parasysh skenarët e parashikuar të punës me të dhënat dhe fillimisht të denormalizojmë të dhënat. Për më tepër, ka disa dallime të tjera, për të cilat do të shkruhet më poshtë.

Le të shqyrtojmë detyrën e mëposhtme "sintetike", me të cilën do të punojmë më tej:

Duhet të dizajnojmë një strukturë për ruajtjen e listës së miqve të përdoruesve të një rrjeti social abstrakt. Për thjeshtësim, do të supozojmë se të gjitha lidhjet janë të drejtuara (si në Instagram, dhe jo si në Linkedin). Strukturë duhet të lejojë që të:

  • PĂ«rgjigjemi pyetjes, a e lexon pĂ«rdoruesi A pĂ«rdoruesin B (shkema e leximit)
  • TĂ« lejojmĂ« shtimin/zhbllokimin e lidhjeve nĂ« rastin e ndjekjes/ndaljes sĂ« pĂ«rdoruesit A nga pĂ«rdoruesi B (shkema e ndryshimit tĂ« tĂ« dhĂ«nave)

Natyrisht, ka shumë mundësi për zgjidhjen e problemit. Në një bazë të dhënash relacionale normale, ne do të bënim një tabelë lidhjesh (ndoshta të tipizuar, nëse, për shembull, ka nevojë për të ruajtur grupin e përdoruesve: familja, puna, etj., në të cilin hyn ky "miku"), dhe për të optimizuar shpejtësinë e aksesit do të shtonim indekse/particionim. Për më tepër, tabela përfundimtare do të dukej ndoshta kështu:

user_id
friend_id

Vasja
Petja

Vasja
Olja

këtu dhe më pas për sqarje dhe kuptim më të mirë në vend të ID do të përcaktoj emrat

Në rastin e HBase e dimë se:

  • kĂ«rkimi efektiv, i cili nuk çon nĂ« njĂ« skanim tĂ« plotĂ« tĂ« tabelĂ«s, Ă«shtĂ« i mundshĂ«m pĂ«rshtatshĂ«m vetĂ«m sipas çelĂ«sit
    • Prandaj, tĂ« shkruash SQL kĂ«rkesa tĂ« njohura pĂ«r shumĂ« njerĂ«z me baza tĂ« tilla Ă«shtĂ« njĂ« ide e keqe; teknikisht, sigurisht, mund tĂ« dĂ«rgosh njĂ« kĂ«rkesĂ« SQL me Join dhe logjikĂ« tjetĂ«r nĂ« HBase nga Impala, por sa e efektshme do tĂ« jetĂ« kjo


Prandaj, ID e përdoruesit ne jemi të detyruar ta përdorim si çelës. Një mendim i parë për temën "ku dhe si të ruajmë ID e miqve?" mund të jetë ideja e ruajtjes së tyre në kolona. Ky variant më i dukshëm dhe "naiv" do të dukej kështu (ta quajmë) Varianti 1 (default), për t'u referuar më pas):

RowKey
Kolonat

Vasja
1: Petja
2: Olya
3: Dasha

Petja
1: Masha
2: Vasya

KĂ«tu, çdo rresht i pĂ«rkon njĂ« pĂ«rdoruesi tĂ« vet nĂ« rrjet. Kolonat kanĂ« emra: 1, 2, ... - sipas numrit tĂ« miqve, dhe nĂ« kolonat ruhen ID e miqve. ËshtĂ« e rĂ«ndĂ«sishme tĂ« theksohet se çdo rresht do tĂ« ketĂ« njĂ« numĂ«r tĂ« ndryshĂ«m kolonash. NĂ« shembullin nĂ« figurĂ«n mĂ« sipĂ«r, njĂ« rresht ka tre kolona (1, 2 dhe 3), ndĂ«rsa i dyti ka vetĂ«m dy (1 dhe 2) - kĂ«tu ne kemi shfrytĂ«zuar dy vetitĂ« e HBase, tĂ« cilat nuk i ka databaza relacional:

  • mundĂ«sinĂ« pĂ«r tĂ« ndryshuar pĂ«rbĂ«rjen e kolonave dinamikisht (shto mikun -> shto kolonĂ«n, hiq mikun -> hiq kolonĂ«n)
  • pĂ«r rreshta tĂ« ndryshĂ«m, pĂ«rbĂ«rja e kolonave mund tĂ« jetĂ« e ndryshme

Le të verifikojmë strukturën tonë në përputhje me kërkesat e detyrës:

  • Leximi i tĂ« dhĂ«nave: pĂ«r tĂ« kuptuar nĂ«se Vasya Ă«shtĂ« i regjistruar tek Olya, na nevojitet tĂ« lexojmĂ« tĂ« gjithĂ« rreshtin me çelĂ«sin RowKey = "Vasya" dhe tĂ« kalojmĂ« pĂ«rmes vlerave tĂ« kolonave, derisa tĂ« "takojmĂ«" Olya nĂ« to. Ose tĂ« kalojmĂ« pĂ«rmes tĂ« gjitha vlerave tĂ« kolonave, "tĂ« mos takojmĂ«" Olya dhe tĂ« kthejmĂ« pĂ«rgjigjen False;
  • Ndryshimi i tĂ« dhĂ«nave: shtimi i mikut: pĂ«r njĂ« detyrĂ« tĂ« tillĂ« na nevojitet gjithashtu tĂ« lexojmĂ« tĂ« gjithĂ« rreshtin me çelĂ«sin RowKey = "Vasya", pĂ«r tĂ« llogaritur numrin total tĂ« miqve tĂ« tij. Ky numĂ«r total miqsh Ă«shtĂ« i nevojshĂ«m pĂ«r tĂ« pĂ«rcaktuar numrin e kolonĂ«s ku duhet tĂ« shkruhet ID i mikut tĂ« ri.
  • Ndryshimi i tĂ« dhĂ«nave: heqja e mikut:
    • Duhet tĂ« lexojmĂ« tĂ« gjithĂ« rreshtin me çelĂ«sin RowKey = "Vasya" dhe tĂ« kalojmĂ« pĂ«rmes kolonave pĂ«r tĂ« gjetur atĂ«, ku Ă«shtĂ« regjistruar miku qĂ« po hiqet;
    • MĂ« pas, pas heqjes sĂ« mikut, ne duhet tĂ« "zhvendosim" tĂ« dhĂ«nat e gjitha njĂ« kolonĂ«, nĂ« mĂ«nyrĂ« qĂ« tĂ« mos marrim "ndarje" nĂ« numĂ«rimin e tyre.

Tani le të vlerësojmë se sa efikas do të jenë algoritmet që na nevojiten për të zbatuar në anën e "aplikacionit të kushteve", duke përdorur O-simbolikënLe të shohim madhësinë e rrjetit tonë hipotetik shoqëror si n. Atëherë numri maksimal i miqve për një përdorues mund të jetë (n-1). Këtë (-1) ne mund ta injorojmë për qëllimet tona, pasi në kuadër të përdorimit të simbolikës O, ajo është e parëndësishme.

  • Leximi i tĂ« dhĂ«nave: nevojitet tĂ« lexojmĂ« tĂ« gjithĂ« rreshtin dhe tĂ« shqyrtojmĂ« nĂ« kufijtĂ« tĂ« gjitha kolonat e tij. KĂ«shtu, vlerĂ«simi i sipĂ«rm i kostove do tĂ« jetĂ« afĂ«rsisht O(n)
  • Ndryshimi i tĂ« dhĂ«nave: shtimi i mikut: pĂ«r tĂ« pĂ«rcaktuar numrin e miqve, ne duhet tĂ« shqyrtojmĂ« tĂ« gjitha kolonat e rreshtit, pas sĂ« cilĂ«s do tĂ« insertojmĂ« njĂ« kolonĂ« tĂ« re => O(n)
  • Ndryshimi i tĂ« dhĂ«nave: heqja e mikut:
    • Po ashtu si nĂ« rastin e shtimit – kĂ«rkohet qĂ« nĂ« kufijtĂ« tĂ« shqyrtojmĂ« tĂ« gjitha kolonat => O(n)
    • Pas fshirjes sĂ« kolonave, na duhen "skaj" ato. NĂ«se e realizojmĂ« kĂ«tĂ« "drejt" do tĂ« nevojiteshin deri nĂ« (n-1) operacione. Por kĂ«tu dhe mĂ« tej nĂ« pjesĂ«n praktike do tĂ« aplikojmĂ« njĂ« qasje tjetĂ«r, e cila do tĂ« realizojĂ« "pseudoskaj" pĂ«rmes njĂ« numri tĂ« fiksuar operacionesh – do tĂ« thotĂ« se do tĂ« shpenzohet njĂ« kohĂ« konstante pavarĂ«sisht n. Kjo kohĂ« konstante (nĂ«se jemi tĂ« saktĂ«, O(2)) nĂ« krahasim me O(n) mund tĂ« injorohet. Qasja ilustrohet nĂ« figurĂ«n mĂ« poshtĂ«: ne thjesht kopjojmĂ« tĂ« dhĂ«nat nga kolonat "e fundit" nĂ« atĂ« nga e cila duam tĂ« fshijmĂ« tĂ« dhĂ«nat, pas sĂ« cilĂ«s fshijmĂ« kolonĂ«n mĂ« tĂ« fundit:
      Karakteristikat e dizajnit të modelit të dhënash për NoSQL

Së fundmi, në të gjitha skenaret ne kemi marrë kompleksitetin asimptotik të llogaritjes O(n).
Mbase tashmë e keni vënë re se ne kemi pothuajse gjithmonë nevojë të lexojmë të gjithë rreshtin nga baza, veçanërisht në dy nga tre rastet vetëm për të shqyrtuar të gjitha kolonat dhe për të llogaritur numrin total të miqve. Prandaj, si një përpjekje optimizimi mund të shtojmë një kolonë "count", ku ruhet numri total i miqve për secilin përdorues në rrjet. Në këtë rast, ne mund të mos lexojmë të gjithë rreshtin për të llogaritur numrin e përgjithshëm të miqve, por të lexojmë vetëm një kolonë "count". E rëndësishme është të mos harrojmë të përditësojmë "count" gjatë manipulimeve me të dhënat. Kështu, arrijmë një përmirësim Opsioni 2 (count):

RowKey
Kolonat

Vasja
1: Petja
2: Olya
3: Dasha
count: 3

Petja
1: Masha
2: Vasya

count: 2

Në krahasim me opsionin e parë:

  • Leximi i tĂ« dhĂ«nave: pĂ«r tĂ« marrĂ« pĂ«rgjigjen pĂ«r pyetjen "A e lexon Vasja OlĂ«n?" nuk ka ndryshuar asgjĂ« => O(n)
  • Ndryshimi i tĂ« dhĂ«nave: shtimi i mikut: E kemi thjeshtuar shtimin e njĂ« miku tĂ« ri, pasi tani nuk na nevojitet tĂ« lexojmĂ« tĂ« toda rreshtin dhe tĂ« kalojmĂ« kolonat e tij, por mund tĂ« marrim vetĂ«m vlerĂ«n e kolonĂ«s «count» dhe kĂ«shtu tĂ« pĂ«rcaktojmĂ« menjĂ«herĂ« numrin e kolonĂ«s pĂ«r tĂ« shtuar mikun e ri. Kjo çon nĂ« uljen e kompleksitetit tĂ« llogaritjes nĂ« O(1)
  • Ndryshimi i tĂ« dhĂ«nave: heqja e mikut: GjatĂ« fshirjes sĂ« njĂ« miku, gjithashtu mund ta pĂ«rdorim kĂ«tĂ« kolonek, pĂ«r tĂ« ulur numrin e operacioneve tĂ« hyrjes dhe daljeve kur «shkarkojmë» tĂ« dhĂ«nat njĂ« hap majtas. Por nevoja pĂ«r tĂ« kaluar nĂ«pĂ«r kolonat pĂ«r tĂ« gjetur atĂ« qĂ« duhet fshirĂ« mbetet, prandaj => O(n)
  • Nga ana tjetĂ«r, tani gjatĂ« pĂ«rditĂ«simit tĂ« tĂ« dhĂ«nave, na duhet tĂ« pĂ«rditĂ«sojmĂ« çdo herĂ« edhe kolonĂ«n «count», por pĂ«r kĂ«tĂ« nevojitet njĂ« kohĂ« konstante, tĂ« cilĂ«n nĂ« kuadĂ«r tĂ« simbolikĂ«s O mund ta injorojmĂ«

Në përgjithësi, opsioni 2 duket pak më optimal, por kjo është më shumë «evolucioni në vend të revolucionit». Për të realizuar një «revolucion» na nevojitet Opsioni 3 (col).
Ta kthejmĂ« gjithçka «pĂ«rmbys»: tĂ« caktojmĂ« emrin e kolonĂ«s identifikues tĂ« pĂ«rdoruesit! ÇfarĂ« do tĂ« regjistrohet nĂ« vetĂ« kolonĂ«n – pĂ«r ne nuk ka rĂ«ndĂ«si, le tĂ« jetĂ« numri 1 (nĂ« tĂ« vĂ«rtetĂ«, nga tĂ« dhĂ«nat e dobishme aty mund tĂ« ruhet, pĂ«r shembull, grupi «familje/mik/etj.». Ky qasje mund tĂ« befasojĂ« njĂ« «pĂ«rfitues» tĂ« papĂ«rgatitur, i cili deri tani nuk ka pasur pĂ«rvojĂ« pune me bazat NoSQL, por pikĂ«risht kjo i lejon tĂ« shfrytĂ«zojĂ« potencialin e HBase nĂ« kĂ«tĂ« detyrĂ« mĂ« efikase:

RowKey
Kolonat

Vasja
Petja: 1
Olja: 1
Dasha: 1

Petja
Masha: 1
Vasia: 1

Këtu ne marrim menjëherë disa avantazhe. Për t'i kuptuar ato, le të analizojmë strukturën e re dhe të vlerësojmë kompleksitetin e llogaritjes:

  • Leximi i tĂ« dhĂ«nave: pĂ«r tĂ« pĂ«rgjigjur pyetjes, nĂ«se Vasia Ă«shtĂ« regjistruar me OljĂ«n, mjafton tĂ« lexojmĂ« njĂ« kolonĂ« «Olja»: nĂ«se ajo Ă«shtĂ« atje, pĂ«rgjigja Ă«shtĂ« True, nĂ«se jo – False => O(1)
  • Ndryshimi i tĂ« dhĂ«nave: shtimi i mikut: Shtimi i njĂ« miku: mjafton tĂ« shtojmĂ« njĂ« kolonĂ« tĂ« re «ID miku» => O(1)
  • Ndryshimi i tĂ« dhĂ«nave: heqja e mikut: mjafton tĂ« fshijmĂ« kolonĂ«n «ID miku» => O(1)

Siç e shohim, njĂ« pĂ«rparĂ«si e madhe e kĂ«saj modeli tĂ« ruajtjes Ă«shtĂ« se nĂ« tĂ« gjitha skenarĂ«t e nevojshĂ«m operojmĂ« vetĂ«m me njĂ« kolonĂ«, duke shmangur leximin e tĂ« dhĂ«nave nga e gjithĂ« rreshti dhe sidomos kalimin nĂ« tĂ« gjitha kolonat e kĂ«tij rreshti. KĂ«tu mund tĂ« ndalojmĂ«, por


Mund tĂ« shqetĂ«sohemi dhe tĂ« shkojmĂ« edhe mĂ« tej nĂ« rrugĂ«n e optimizimit tĂ« performancĂ«s dhe reduktimit tĂ« operacioneve tĂ« hyrjes-dalinjes kur i drejtohemi bazĂ«s. ÇfarĂ« ndodh nĂ«se ruajmĂ« informacionin e plotĂ« tĂ« lidhjes drejtpĂ«rdrejt nĂ« çelĂ«sin e rreshtit? DomethĂ«nĂ«, ta bĂ«jmĂ« çelĂ«sin tĂ« pĂ«rbĂ«rĂ« nga userID.friendID? NĂ« kĂ«tĂ« rast, madje nuk na nevojitet tĂ« lexojmĂ« kolonat e rreshtit.Opsioni 4 (rreshti)):

RowKey
Kolonat

Vasja.Petja
Petja: 1

Vasja.Olja
Olja: 1

Vasja.Dasha
Dasha: 1

Petja.Masha
Masha: 1

Petja.Vasja
Vasia: 1

ËshtĂ« e qartĂ« se vlerĂ«simi i tĂ« gjithĂ« skenarĂ«ve tĂ« manipulimit tĂ« tĂ« dhĂ«nave nĂ« kĂ«tĂ« strukturĂ«, ashtu si nĂ« opsionin e mĂ«parshĂ«m, do tĂ« jetĂ« O(1). Ndryshimi me opsionin 3 do tĂ« jetĂ« thjesht nĂ« efikasitetin e operacioneve tĂ« hyrjes-dalinjes nĂ« DB.

Dhe, pĂ«rfundimisht, njĂ« "kalim i fundit". ËshtĂ« e lehtĂ« tĂ« vĂ«resh se nĂ« opsionin 4 çelĂ«si i rreshtit do tĂ« ketĂ« njĂ« gjatĂ«si tĂ« ndryshueshme, qĂ« ndoshta mund tĂ« ndikojĂ« nĂ« performancĂ« (kĂ«tu kujtojmĂ« se HBase ruan tĂ« dhĂ«nat si njĂ« grup bajtesh dhe rreshtat nĂ« tabela janĂ« tĂ« renditur sipas çelĂ«sit). Plus, kemi njĂ« ndarĂ«s, i cili nĂ« disa skenarĂ« mund tĂ« kĂ«rkojĂ« trajtim. PĂ«r tĂ« eliminuar kĂ«tĂ« ndikim, mund tĂ« pĂ«rdorim hash-e nga userID dhe friendID, dhe pasi tĂ« dy hash-et do tĂ« kenĂ« gjatĂ«si fikse, mund thjesht t'i konkatenujmĂ« ato, pa ndarĂ«s. AtĂ«herĂ« tĂ« dhĂ«nat nĂ« tavolinĂ« do tĂ« duken kĂ«shtu (Opsioni 5 (hash)):

RowKey
Kolonat

dc084ef00e94aef49be885f9b01f51c01918fa783851db0dc1f72f83d33a5994
Petja: 1

dc084ef00e94aef49be885f9b01f51c0f06b7714b5ba522c3cf51328b66fe28a
Olja: 1

dc084ef00e94aef49be885f9b01f51c00d2c2e5d69df6b238754f650d56c896a
Dasha: 1

1918fa783851db0dc1f72f83d33a59949ee3309645bd2c0775899fca14f311e1
Masha: 1

1918fa783851db0dc1f72f83d33a5994dc084ef00e94aef49be885f9b01f51c0
Vasia: 1

ËshtĂ« e qartĂ« se kompleksiteti algoritmik i punĂ«s me njĂ« strukturĂ« tĂ« tillĂ« pĂ«r skenarĂ«t qĂ« po shqyrtojmĂ« do tĂ« jetĂ« i njĂ«jtĂ« me opsionin 4 – dmth O(1).
Pra, do ta përmbledhim të gjithë vlerësimin tonë të kompleksitetit të llogaritjeve në një tabelë:

Shtimi i një miku
Kontrollimi i mikut
Fshirja e mikut

Varianti 1 (default)
O(n)
O(n)
O(n)

Opsioni 2 (count)
O(1)
O(n)
O(n)

Opsioni 3 (kolona)
O(1)
O(1)
O(1)

Opsioni 4 (rreshti)
O(1)
O(1)
O(1)

Opsioni 5 (hash)
O(1)
O(1)
O(1)

Siç duket, opsionet 3-5 duken më të preferuara dhe teorikisht sigurojnë përmbushjen e të gjitha skenarëve të nevojshme për manipulimin e të dhënave në një kohë konstante. Në kushtet e detyrës tonë nuk ka kërkesa të qarta për të marrë një listë të të gjitha miqve të përdoruesit, por në aktivitetin tonë të projektit, si analistë të mirë, do të ishte e mençur të "parashikojmë" se një detyrë e tillë mund të lindë dhe ta "përgatitim" vetveten. Prandaj, preferencat e mia janë për opsionin 3. Por është krejtësisht e mundur që në një projekt të vërtetë kjo kërkesë të jetë zgjidhur me mjete të tjera, prandaj pa një vizion të plotë të detyrës, nuk duhet të nxjerrim përfundime të përfundshme.

Përgatitja e eksperimentit

DĂ«shirojmĂ« t'i verifikojmĂ« kĂ«to mendime teorike nĂ« praktikĂ« – kjo ishte qĂ«llimi qĂ« lindi gjatĂ« fundjavĂ«s sĂ« gjatĂ«. PĂ«r kĂ«tĂ«, Ă«shtĂ« e nevojshme tĂ« vlerĂ«sojmĂ« shpejtĂ«sinĂ« e punĂ«s sĂ« "aplikacionit tonĂ« tĂ« kushtuar" nĂ« tĂ« gjitha skenarĂ«t e pĂ«rshkruar pĂ«r pĂ«rdorimin e databazĂ«s, si dhe rritjen e kĂ«tij koha me rritjen e madhĂ«sisĂ« sĂ« rrjetit social (n). Parametri i synuar qĂ« na intereson dhe qĂ« do tĂ« masim gjatĂ« eksperimentit, Ă«shtĂ« koha e shpenzuar nga "aplikacioni i kushtuar" pĂ«r tĂ« kryer njĂ« "operacion biznesi". Me "operacion biznesi" kuptojmĂ« njĂ« nga sa vijon:

  • Shtimi i njĂ« miku tĂ« ri
  • Kontrollimi i shtyrjes nĂ«se pĂ«rdoruesi A Ă«shtĂ« mik i pĂ«rdoruesit B
  • Fshirja e njĂ« miku

Prandaj, duke pasur parasysh kërkesat e shtruara në fillim, skenari i kontrollit shfaqet si vijon:

  • Shkruaj tĂ« dhĂ«nat. TĂ« gjenerohet rastĂ«sisht njĂ« rrjet fillestar me madhĂ«sinĂ« n. PĂ«r njĂ« afĂ«rsi mĂ« tĂ« madhe me "botĂ«n reale", numri i miqve tĂ« çdo pĂ«rdoruesi Ă«shtĂ« gjithashtu njĂ« vlerĂ« rastĂ«sore. TĂ« masim kohĂ«n gjatĂ« sĂ« cilĂ«s "aplikacioni ynĂ« i kushtuar" do tĂ« shkrijĂ« tĂ« gjitha tĂ« dhĂ«nat e gjeneruara nĂ« HBase. MĂ« pas, tĂ« ndajmĂ« kohĂ«n e marrĂ« me numrin total tĂ« miqve tĂ« shtuar – ashtu do tĂ« marrim kohĂ«n mesatare pĂ«r njĂ« "operacion biznesi".
  • Leximi i tĂ« dhĂ«nave. PĂ«r çdo pĂ«rdorues, pĂ«rgatitni njĂ« listĂ« "identitetesh" pĂ«r tĂ« cilat duhet tĂ« kontrolloni nĂ«se pĂ«rdoruesi Ă«shtĂ« ndjekĂ«s i tyre apo jo. GjatĂ«sia e listĂ«s Ă«shtĂ« afĂ«rsisht sa numri i miqve tĂ« pĂ«rdoruesit, ku pĂ«r gjysmĂ«n e miqve tĂ« kontrolluar, pĂ«rgjigja duhet tĂ« jetĂ« "Po", ndĂ«rsa pĂ«r gjysmĂ«n tjetĂ«r – "Jo". Kontrolli bĂ«het nĂ« njĂ« renditje tĂ« tillĂ« qĂ« pĂ«rgjigjet "Po" dhe "Jo" tĂ« alternohen (dmth. nĂ« çdo rast tĂ« dytĂ« na duhet tĂ« kontrollojmĂ« tĂ« gjitha kolonat e rreshtit pĂ«r variantet 1 dhe 2). Koha e pĂ«rgjithshme e kontrollit mĂ« pas ndahet me numrin e miqve tĂ« kontrolluar pĂ«r tĂ« marrĂ« kohĂ«n mesatare pĂ«r kontrollin e njĂ« subjekti.
  • Fshirja e tĂ« dhĂ«nave. Fshihni tĂ« gjithĂ« miqtĂ« e pĂ«rdoruesit. Renditja e fshirjes Ă«shtĂ« rastĂ«sore (dmth. "pĂ«rzierim" i listĂ«s fillestare qĂ« Ă«shtĂ« pĂ«rdorur pĂ«r regjistrimin e tĂ« dhĂ«nave). Koha e pĂ«rgjithshme e kontrollit mĂ« pas ndahet me numrin e miqve tĂ« fshirĂ« pĂ«r tĂ« marrĂ« kohĂ«n mesatare pĂ«r njĂ« kontroll.

Skenarët duhet të kalohen për çdo një nga 5 variantet e modeleve të të dhënave dhe për madhësi të ndryshme të rrjetit social, për të parë se si ndryshon koha me rritjen e tij. Brenda një n lidhjeje në rrjet dhe lista e përdoruesve për kontroll duhet të jetë, natyrisht, e njëjtë për të gjithë 5 variantet.
Për një kuptim më të mirë, më poshtë po sjell një shembull të të dhënave të gjeneruara për n= 5. "Generatori" i shkruar jep si rezultat tre fjalorë ID-sh:

  • i pari – pĂ«r futjen
  • i dyti – pĂ«r kontrollin
  • i tretĂ« – pĂ«r fshirjen

{0: [1], 1: [4, 5, 3, 2, 1], 2: [1, 2], 3: [2, 4, 1, 5, 3], 4: [2, 1]} # gjithsej 15 miq

{0: [1, 10800], 1: [5, 10800, 2, 10801, 4, 10802], 2: [1, 10800], 3: [3, 10800, 1, 10801, 5, 10802], 4: [2, 10800]} # gjithsej 18 subjekte të kontrolluara

{0: [1], 1: [1, 3, 2, 5, 4], 2: [1, 2], 3: [4, 1, 2, 3, 5], 4: [1, 2]} # gjithsej 15 miq

Siç mund të vëreni, të gjitha ID, të mëdha se 10 000 në fjalorin për kontroll, janë ato që me siguri do të japin përgjigje False. Futja, kontrolli dhe fshirja e "miqve" bëhen pikërisht në rendin e specifikuar në fjalor.

Eksperimenti u zhvillua nĂ« njĂ« laptop me sistemin Windows 10, ku nĂ« njĂ« konteiner Docker ishte e vendosur njĂ« bazĂ« HBase, ndĂ«rsa nĂ« konteinerin tjetĂ«r – Python me Jupyter Notebook. Docker-it i ishin dhĂ«nĂ« 2 bĂ«rthama CPU dhe 2 GB pĂ«rmemorie. E gjithĂ« logjika, si simuluar e funksionit tĂ« "aplikacionit tĂ« mundshĂ«m", ashtu edhe "mbĂ«shtetje" pĂ«r gjenerimin e tĂ« dhĂ«nave testuese dhe regjistrimin e kohĂ«s ishin shkruar nĂ« Python. PĂ«r punĂ« me HBase u pĂ«rdor biblioteka happybase, pĂ«r llogaritjen e hash-Ă«ve (MD5) pĂ«r variantin 5 — hashlib

Duke marrĂ« parasysh fuqinĂ« computing tĂ« laptopit tĂ« caktuar, pĂ«rvojĂ« eksperimentale u zgjodh tĂ« fillojĂ« pĂ«r n = 10, 30, 
. 170 – kur koha totale e funksionimit tĂ« ciklit tĂ« plotĂ« tĂ« testimit (tĂ« gjitha skenarĂ«t pĂ«r tĂ« gjitha variantet pĂ«r tĂ« gjithĂ« n) ishte akoma mĂ« shumĂ« ose mĂ« pak e arsyeshme dhe pĂ«rfshihej brenda kohĂ«s njĂ« çaji (nĂ« mesatare 15 minuta).

Këtu është e nevojshme të bëhet një shënim, se në këtë eksperiment ne vlerësojmë kryesisht jo shifrat absolute të performancës. Edhe krahasimi relativ i dy varianteve të ndryshme mund të mos jetë plotësisht korrekt. Aktualisht, na intereson natyra e ndryshimit të kohës në varësi të n, pasi duke marrë parasysh konfigurimin e mësipërm të "testit të qendrës" është shumë e vështirë të merret një vlerësim kohor, "i pastruar" nga ndikimet rastësore dhe faktorë të tjerë (dhe asnjëherë nuk është vendosur një qëllim të tillë).

Rezultati i eksperimentit

Testi i parĂ« – si ndryshon koha e kaluar pĂ«r mbushjen e listĂ«s sĂ« miqve. Rezultati – nĂ« grafikĂ«n mĂ« poshtĂ«.
Karakteristikat e dizajnit të modelit të dhënash për NoSQL
Variantet 3-5 pritet të tregojnë praktikisht një kohë konstante të "veprës afariste", e cila nuk varet nga rritja e madhësisë së rrjetit dhe diferenca e pamundshme në performancë.
Varianti 2 gjithashtu tregon një performancë konstante, por pak më të dobët, dhe në mënyrë të përafërt dyfish në krahasim me variantet 3-5. Dhe kjo nuk mund të mos gëzojë, pasi përputhet me teorinë - në këtë variant numri i operacioneve të hyrjes-daljes në/nga HBase është pikërisht dyfish më i madh. Kjo mund të shërbejë si një dëshmi indirekte se qendra jonë testuese në parim siguron një saktësi të mirë.
Varianti 1 gjithashtu është siç pritej më i ngadalshëm dhe tregon një rritje lineare të kohës së kaluar për shtimin e një miku në varësi të madhësisë së rrjetit.
Tani le të shikojmë rezultatet e testit të dytë.
Karakteristikat e dizajnit të modelit të dhënash për NoSQL
Opsionet 3-5 pĂ«rsĂ«ri veprojnĂ« siç pritej – kohĂ« konstante, e cila nuk varet nga madhĂ«sia e rrjetit. Opsionet 1 dhe 2 tregojnĂ« njĂ« rritje lineare tĂ« kohĂ«s me rritjen e madhĂ«sisĂ« sĂ« rrjetit dhe njĂ« performancĂ« tĂ« ngjashme. NĂ« veçanti, opsioni 2 rezulton pak mĂ« i ngadalshĂ«m – duket se pĂ«r shkak tĂ« nevojĂ«s pĂ«r tĂ« lexuar dhe trajtuar njĂ« kolonĂ« shtesĂ« "count", e cila bĂ«het mĂ« e dukshme me rritjen e n. MegjithatĂ«, do tĂ« pĂ«rmbahem nga çdo pĂ«rfundim, pasi saktĂ«sia e kĂ«tij krahasimi Ă«shtĂ« relativisht e ulĂ«t. PĂ«r mĂ« tepĂ«r, kĂ«to raporte (cilat opsione, 1 apo 2, janĂ« mĂ« tĂ« shpejta) ndryshonin nga njĂ« ekzekutim nĂ« tjetrin (ndĂ«rsa ruanin karakterin e varĂ«sisĂ« dhe "shkonin krahas")

Dhe grafiku i fundit – rezultati i testit tĂ« fshirjes.

Karakteristikat e dizajnit të modelit të dhënash për NoSQL

Këtu përsëri pa surpriza. Opsionet 3-5 realizojnë fshirjen në kohë konstante.
Dhe, çka është interesante, opsionet 4 dhe 5, ndryshe nga skenarët e mëparshëm, tregojnë një performancë disi më të ulët se opsioni 3. Dukshëm, operacioni i fshirjes së një rreshti është më i shtrenjtë se operacioni i fshirjes së një kolone, që në përgjithësi është logjike.

Opsionet 1 dhe 2, siç pritej, tregojnĂ« njĂ« rritje lineare tĂ« kohĂ«s. NĂ« kĂ«tĂ« rast, opsioni 2 vazhdimisht Ă«shtĂ« mĂ« i ngadaltĂ« se opsioni 1 – pĂ«r shkak tĂ« operacionit shtesĂ« tĂ« hyrjes dhe daljes pĂ«r "mirĂ«mbajtjen" e kolonĂ«s count.

Përfundimet e përgjithshme të eksperimentit:

  • Opsionet 3-5 demonstrojnĂ« njĂ« efikasitet mĂ« tĂ« lartĂ«, pasi ato shfrytĂ«zojnĂ« avantazhet e HBase; ndĂ«rsa performanca e tyre ndryshon njĂ«ra me tjetrĂ«n me njĂ« konstant dhe nuk varet nga madhĂ«sia e rrjetit.
  • Diferenca midis opsioneve 4 dhe 5 nuk Ă«shtĂ« regjistruar. Por kjo nuk do tĂ« thotĂ« se opsioni 5 nuk duhet pĂ«rdorur. Ka shumĂ« mundĂ«si qĂ« skenari i pĂ«rdorur nĂ« eksperiment, duke marrĂ« parasysh TTX e vendit tĂ« provĂ«s, nuk e mundĂ«soi tĂ« zbulohej.
  • Natyra e rritjes sĂ« kohĂ«s sĂ« nevojshme pĂ«r tĂ« realizuar "operacionet biznesore" me tĂ« dhĂ«na, nĂ« pĂ«rgjithĂ«si konfirmoi pĂ«rfundimet teorike tĂ« mĂ«parshme pĂ«r tĂ« gjitha opsionet.

Epilogu

Eksperimet e bëra nuk duhet të merren si e vërtetë absolute. Ekzistojnë shumë faktorë që nuk janë marrë parasysh dhe që kanë sjellë disa devijime në rezultatet (veçanërisht këto fluktuacione duken qartë në grafikë kur dimensioni i rrjetit është i vogël). Për shembull, shpejtësia e Thrift-it, i cili përdoret nga Happybase, volume dhe mënyra e zbatimit të logjikës që kam shkruar në Python (nuk pretendoj se kodi është shkruar në mënyrë optimale dhe që përdor maksimumin e mundësive të të gjithë komponenteve), mundësisht karakteristikat e caching-ut të HBase, aktiviteti në sfond i Windows 10 në laptopin tim etj. Në përgjithësi, mund të mendohet se të gjitha përllogaritjet teorike e kanë dëshmuar vlerën e tyre eksperimentale. Ose të paktën nuk ka qenë e mundur të hedhim poshtë këto përllogaritje me një goditje të tillë të drejtpërdrejtë.

NĂ« pĂ«rfundim – rekomandime pĂ«r tĂ« gjithĂ« ata qĂ« sapo po fillojnĂ« tĂ« projektojnĂ« modele tĂ« dhĂ«nash nĂ« HBase: abstrahohuni nga pĂ«rvoja e mĂ«parshme me bazat e tĂ« dhĂ«nave relacionale dhe mbani mend "shqiponjat":

  • Kur projektojmĂ«, fillojmĂ« nga detyra dhe modelet e manipulimit me tĂ« dhĂ«nat, dhe jo nga modeli i fushĂ«s sĂ« subjektit.
  • Qasje efikase (pa skanim tĂ« plotĂ« tĂ« tabelĂ«s) - vetĂ«m pĂ«rmes çelĂ«sit.
  • Denormalizimi.
  • Rreshta tĂ« ndryshĂ«m mund tĂ« pĂ«rmbajnĂ« kolona tĂ« ndryshme.
  • PĂ«rbĂ«rje dinamike e koloneve.

Burimi: habr.com

Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS đŸ”„ Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS | ProHoster