Designprinciper för datamodellen för NoSQL

Introduktion

Designprinciper för datamodellen för NoSQL «Man mÄste springa för allt man Àr vÀrd för att bara stanna kvar,
och för att komma nÄgonstans mÄste man springa minst dubbelt sÄ snabbt!»
(c) Alice i Underlandet

För ett tag sedan blev jag ombedd att hÄlla en förelÀsning till analytikerna i vÄrt företag om datamodellering, eftersom vi, efter att ha suttit lÀnge pÄ projekt (ibland i flera Är), missar vad som hÀnder runt omkring i vÀrlden av IT-teknologier. I vÄrt företag (sÄ har det blivit) anvÀnds inte NoSQL-databaser pÄ mÄnga projekt (Ätminstone inte Àn), sÄ i min förelÀsning Àgnade jag sÀrskild uppmÀrksamhet Ät dem med HBase som exempel och försökte rikta presentationen till dem som aldrig har arbetat med dem. Jag illustrerade sÀrskilt nÄgra egenskaper av datamodellering med ett exempel som jag lÀste för flera Är sedan i artikeln «Introduction to HBase Schema Design» av Amandeep Khurana. Genom att analysera exemplen jÀmförde jag flera lösningar pÄ samma problem för att bÀttre förmedla de grundlÀggande idéerna till Ähörarna.

Nyligen, «för att ha nÄgot att göra», stÀllde jag mig frÄgan (de lÄnga majhelgerna i karantÀnlÀge gör detta sÀrskilt aktuellt) hur teoretiska slutsatser skulle stÀmma överens med praktiken? SÄ föddes idén till den hÀr artikeln. En utvecklare som har jobbat med NoSQL ett tag kanske inte kommer att fÄ ut nÄgot nytt av den (och kan dÀrför direkt scrolla igenom halva artikeln). Men för analytikerna, som Ànnu inte har arbetat nÀra med NoSQL, tror jag att den kommer att vara anvÀndbar för att fÄ grundlÀggande insikter om datamodellering för HBase.

Analys av exemplet

Enligt min Äsikt bör man tÀnka noga pÄ för- och nackdelar innan man börjar anvÀnda NoSQL-databaser. Ofta kan uppgiften sannolikt lösas Àven med traditionella relationsdatabaser. DÀrför Àr det bÀttre att inte anvÀnda NoSQL utan betydande skÀl. Om man ÀndÄ har beslutat att anvÀnda en NoSQL-databas, bör man beakta att designmetoderna hÀr skiljer sig nÄgot. SÀrskilt vissa av dem kan vara ovanliga för dem som tidigare endast har arbetat med relationsdatabaser (enligt mina observationer). SÄ i den "relationsbaserade" vÀrlden gÄr vi vanligtvis frÄn modellering av ÀmnesomrÄdet och sedan, vid behov, utför vi denormalisering av modellen. I NoSQL mÄste vi omedelbart ta hÀnsyn till de förvÀntade anvÀndningsscenarierna för data och initialt denormalisera data. Dessutom finns det en rad andra skillnader, som kommer att beskrivas nedan.

LÄt oss betrakta följande "syntetiska" uppgift, som vi kommer att arbeta med framöver:

Det Àr nödvÀndigt att designa en lagringsstruktur för en lista över anvÀndares vÀnner i ett visst abstrakt socialt nÀtverk. För att förenkla antar vi att alla relationer Àr riktade (som pÄ Instagram, inte pÄ LinkedIn). Strukturen bör möjliggöra effektivt:

  • Att besvara frĂ„gan om anvĂ€ndare A lĂ€ser anvĂ€ndare B (lĂ€sningsmönster)
  • Möjliggöra att lĂ€gga till/ta bort relationer vid abonnemang/avprenumeration av anvĂ€ndare A frĂ„n anvĂ€ndare B (datamönster för förĂ€ndring)

SjÀlvklart finns det mÄnga sÀtt att lösa uppgiften. I en vanlig relationsdatabas skulle vi förmodligen bara gjort en relations-tabell (möjligen typad, om vi till exempel behöver lagra en anvÀndargrupp: familj, arbete etc., som denna "vÀn" tillhör), och för att optimera Ätkomsthastigheten skulle vi ha lagt till index/partitionering. Troligtvis skulle den slutliga tabellen se ungefÀr ut sÄ hÀr:

user_id
friend_id

Vasya
Petya

Vasya
Olya

HÀr och framöver kommer jag för tydlighetens skull att ange namn istÀllet för ID

I fallet med HBase vet vi att:

  • effektiv sökning som inte leder till fullstĂ€ndig tabellskanning Ă€r möjligt exklusivt med nyckel
    • Just dĂ€rför Ă€r det en dĂ„lig idĂ© att skriva de vanliga SQL-frĂ„gorna till sĂ„dana databaser; tekniskt sett kan du sjĂ€lvklart skicka en SQL-frĂ„ga med joins och annan logik frĂ„n samma Impala till HBase, men hur effektivt kommer det att vara


DÀrför mÄste vi anvÀnda anvÀndarens ID som nyckel. En första tanke kring "var och hur lagra vÀnners ID?" kan vara att lagra dem i kolumner. Det mest uppenbara och "naiva" alternativet kan se ut ungefÀr sÄ hÀr (lÄt oss kalla det Alternativ 1 (standard), för att referera till det senare):

RowKey
Kolumner

Vasya
1: Petya
2: Olya
3: Dasha

Petya
1: Masha
2: Vasya

HĂ€r motsvarar varje rad en anvĂ€ndare av nĂ€tverket. Kolumnerna har namn: 1, 2, 
 — motsvarande antalet vĂ€nner, och i kolumnerna lagras vĂ€nners ID. Det Ă€r viktigt att notera att varje rad kan ha ett olika antal kolumner. I exemplet ovan har en rad tre kolumner (1, 2 och 3), medan den andra har endast tvĂ„ (1 och 2) – hĂ€r anvĂ€nde vi tvĂ„ egenskaper hos HBase som inte finns i relationsdatabaser:

  • möjligheten att dynamiskt Ă€ndra sammansĂ€ttningen av kolumner (lĂ€gger till en vĂ€n -> lĂ€gger till en kolumn, tar bort en vĂ€n -> tar bort en kolumn)
  • olika rader kan ha olika sammansĂ€ttningar av kolumner

LÄt oss nu kontrollera vÄr struktur mot kraven i uppgiften:

  • LĂ€sa data: för att förstĂ„ om Vasya följer Olya mĂ„ste vi lĂ€sa hela raden med nyckeln RowKey = "Vasya" och gĂ„ igenom kolumnvĂ€rdena tills vi "trĂ€ffar" Olya. Eller gĂ„ igenom vĂ€rdena för alla kolumner, "inte trĂ€ffa" Olya och returnera False;
  • Ändra data: lĂ€gga till en vĂ€n: för en sĂ„dan uppgift behöver vi ocksĂ„ lĂ€sa hela raden med nyckeln RowKey = "Vasya", för att rĂ€kna det totala antalet av hans vĂ€nner. Detta totala antal vĂ€nner behöver vi för att bestĂ€mma kolumnnumret dĂ€r vi ska skriva ID för den nya vĂ€nnen.
  • Ändra data: ta bort en vĂ€n:
    • Det behövs en lĂ€sning hela raden med nyckeln RowKey = "Vasya" och gĂ„ igenom kolumnerna för att hitta den som innehĂ„ller den borttagna vĂ€nnen;
    • Sedan mĂ„ste vi efter att ha tagit bort vĂ€nnen "flytta" alla data en kolumn över, sĂ„ att vi inte fĂ„r nĂ„gra "hĂ„l" i deras numrering.

LÄt oss nu bedöma hur effektiva de algoritmer som vi mÄste implementera pÄ sidan av "det hypotetiska programmet" blir, genom att anvÀnda O-symbolikLÄt oss definiera storleken pÄ vÄrt hypotetiska sociala nÀtverk som n. Den maximala antalet vÀnner en anvÀndare kan ha Àr (n-1). Denna (-1) kan vi bortse ifrÄn för vÄra syften, eftersom den Àr obetydlig inom ramen för anvÀndning av O-symbolik.

  • LĂ€sa data: det Ă€r nödvĂ€ndigt att lĂ€sa hela raden och gĂ„ igenom alla dess kolumner. SĂ„ledes blir den övre grĂ€nsen för kostnaden cirka O(n)
  • Ändra data: lĂ€gga till en vĂ€n: för att faststĂ€lla antalet vĂ€nner mĂ„ste vi gĂ„ igenom alla kolumner i raden, varefter vi lĂ€gger till en ny kolumn => O(n)
  • Ändra data: ta bort en vĂ€n:
    • PĂ„ liknande sĂ€tt som vid tillĂ€gg – det krĂ€vs att gĂ„ igenom alla kolumner => O(n)
    • Efter att ha tagit bort kolumnerna mĂ„ste vi ”flytta” dem. Om vi genomför detta ”direkt”, krĂ€vs det ytterligare upp till (n-1) operationer. Men hĂ€r och framĂ„t kommer vi att tillĂ€mpa en annan metod i den praktiska delen, som kommer att genomföra en ”pseudo-flytt” pĂ„ ett fast antal operationer – det vill sĂ€ga, det kommer att ta konstant tid oavsett n. Denna konstanta tiden (om vi ska vara exakta, O(2)) kan bortses ifrĂ„n jĂ€mfört med O(n). Metoden illustreras i bilden nedan: vi kopierar helt enkelt data frĂ„n den ”sista” kolumnen till den dĂ€r vi mĂ„ste ta bort data, varefter vi tar bort den sista kolumnen:
      Designprinciper för datamodellen för NoSQL

Sammanfattningsvis har vi i alla scenarier fÄtt en asymptotisk berÀkningskomplexitet O(n).
Du har kanske redan lagt mĂ€rke till att vi nĂ€stan alltid mĂ„ste lĂ€sa hela raden frĂ„n databasen, och i tvĂ„ av tre fall bara för att gĂ„ igenom alla kolumner och rĂ€kna det totala antalet vĂ€nner. DĂ€rför, som ett försök till optimering, kan vi lĂ€gga till en kolumn ”count” dĂ€r det totala antalet vĂ€nner för varje anvĂ€ndare i nĂ€tverket lagras. PĂ„ det hĂ€r sĂ€ttet behöver vi inte lĂ€sa hela raden för att rĂ€kna det totala antalet vĂ€nner, utan kan lĂ€sa endast en kolumn ”count”. Det viktigaste Ă€r att inte glömma att uppdatera ”count” nĂ€r vi manipulerar med data. SĂ„ledes fĂ„r vi en förbĂ€ttrad Alternativ 2 (count):

RowKey
Kolumner

Vasya
1: Petya
2: Olya
3: Dasha
count: 3

Petya
1: Masha
2: Vasya

count: 2

JÀmfört med det första alternativet:

  • LĂ€sa data: för att fĂ„ svaret pĂ„ frĂ„gan ”LĂ€ser Vasja Olya?” har inget förĂ€ndrats => O(n)
  • Ändra data: lĂ€gga till en vĂ€n: Vi har förenklat införandet av en ny vĂ€n, eftersom vi nu inte behöver gĂ„ igenom hela raden och iterera över dess kolumner, utan kan fĂ„ vĂ€rdet frĂ„n kolumnen "count" och dĂ€rmed direkt bestĂ€mma vilken kolumn som ska anvĂ€ndas för att införa en ny vĂ€n. Detta minskar den berĂ€kningsmĂ€ssiga komplexiteten till O(1)
  • Ändra data: ta bort en vĂ€n: NĂ€r vi tar bort en vĂ€n kan vi ocksĂ„ anvĂ€nda denna kolumn för att minska antalet in- och utdataoperationer vid "skiftningen" av data en cell Ă„t vĂ€nster. Men behovet av att iterera genom kolumnerna för att hitta den som ska tas bort kvarstĂ„r, sĂ„ => O(n)
  • Å andra sidan mĂ„ste vi nu vid uppdatering av data varje gĂ„ng ocksĂ„ uppdatera kolumnen "count", men detta tar konstant tid, vilket i O-notering kan försummas

Överlag framstĂ„r alternativ 2 som nĂ„got mer optimalt, men det Ă€r snarare en "evolution Ă€n en revolution". För att genomföra en "revolution" behöver vi Alternativ 3 (col).
LÄt oss vÀnda allt "upp och ner": vi namnger kolumnen med anvÀndarens identifierare! Vad som kommer att skrivas i sjÀlva kolumnen spelar ingen roll för oss, lÄt det vara siffran 1 (allmÀnt kan vi lagra exempelvis gruppen "familj/vÀnner/osv."). Denna metod kan överraska den ovana "medborgaren", som inte haft erfarenhet av NoSQL-databaser, men just den gör det möjligt att utnyttja potentialen hos HBase i detta uppdrag mycket mer effektivt:

RowKey
Kolumner

Vasya
Petya: 1
Olya: 1
Dasha: 1

Petya
Masha: 1
Vasya: 1

HÀr fÄr vi omedelbart flera fördelar. För att förstÄ dem, lÄt oss analysera den nya strukturen och bedöma den berÀkningsmÀssiga komplexiteten:

  • LĂ€sa data: för att svara pĂ„ frĂ„gan om Vasya har prenumererat pĂ„ Olya, rĂ€cker det att lĂ€sa en kolumn "Olya": om den finns, Ă€r svaret True, om inte – False => O(1)
  • Ändra data: lĂ€gga till en vĂ€n: TillsĂ€ttning av en vĂ€n: det rĂ€cker med att bara lĂ€gga till en ny kolumn "vĂ€ns ID" => O(1)
  • Ändra data: ta bort en vĂ€n: det rĂ€cker med att bara ta bort kolumnen "vĂ€ns ID" => O(1)

Som vi ser Ă€r en betydande fördel med denna lagringsmodell att vi i alla vĂ„ra nödvĂ€ndiga scenarier endast arbetar med en kolumn, vilket undviker att lĂ€sa hela raden frĂ„n databasen och förstĂ„s att iterera genom alla kolumner i denna rad. Det skulle kunna vara slutet pĂ„ detta, men


Man kan fundera pÄ att gÄ lÀngre i att optimera prestanda och minska in- och utdataoperationer nÀr det gÀller databasen. Vad sÀgs om att lagra fullstÀndig informationskoppling direkt i nyckeln för raden? Det vill sÀga göra nyckeln sammansatt i formen userID.friendID? I sÄ fall kan vi inte ens behöva lÀsa kolumnerna i raden.Alternativ 4(row)):

RowKey
Kolumner

Vasya.Petya
Petya: 1

Vasya.Olya
Olya: 1

Vasya.Dasha
Dasha: 1

Petya.Masha
Masha: 1

Petya.Vasya
Vasya: 1

Det Àr uppenbart att bedömningen av alla scenarier för datamanipulation i en sÄdan struktur, precis som i den tidigare varianten, ocksÄ kommer att vara O(1). Skillnaden med alternativ 3 kommer att ligga uteslutande i effektiviteten för in- och utdataoperationer i databasen.

Och den sista "slipsen". Det Àr enkelt att se att i alternativ 4 kommer nyckeln för raden att ha en variabel lÀngd, vilket eventuellt kan pÄverka prestandan (hÀr pÄminner vi oss om att HBase lagrar data som en uppsÀttning byte och rader i tabeller sorteras efter nyckel). Dessutom har vi en avskiljare som i vissa scenarier kan behöva bearbetas. För att utesluta denna pÄverkan kan vi anvÀnda hashvÀrden frÄn userID och friendID, och eftersom bÄda hashvÀrdena kommer att ha konstant lÀngd kan vi helt enkelt konkatenera dem utan avskiljare. DÄ kommer datan i tabellen att se ut sÄ hÀr:Alternativ 5(hash)):

RowKey
Kolumner

dc084ef00e94aef49be885f9b01f51c01918fa783851db0dc1f72f83d33a5994
Petya: 1

dc084ef00e94aef49be885f9b01f51c0f06b7714b5ba522c3cf51328b66fe28a
Olya: 1

dc084ef00e94aef49be885f9b01f51c00d2c2e5d69df6b238754f650d56c896a
Dasha: 1

1918fa783851db0dc1f72f83d33a59949ee3309645bd2c0775899fca14f311e1
Masha: 1

1918fa783851db0dc1f72f83d33a5994dc084ef00e94aef49be885f9b01f51c0
Vasya: 1

Det Ă€r uppenbart att den algoritmiska komplexiteten för att arbeta med en sĂ„dan struktur i de scenarier vi övervĂ€ger kommer att vara densamma som för alternativ 4 – det vill sĂ€ga O(1).
Sammanfattningsvis, lÄt oss sammanfatta alla vÄra bedömningar av den berÀkningsmÀssiga komplexiteten i en tabell:

LÀgga till vÀn
Kontrollera vÀn
Ta bort vÀn

Alternativ 1 (standard)
O(n)
O(n)
O(n)

Alternativ 2 (count)
O(1)
O(n)
O(n)

Alternativ 3 (column)
O(1)
O(1)
O(1)

Alternativ 4 (row)
O(1)
O(1)
O(1)

Alternativ 5 (hash)
O(1)
O(1)
O(1)

Som det framgÄr verkar alternativ 3-5 vara de mest föredragna och teoretiskt sett sÀkerstÀller de att alla nödvÀndiga datamanipulationsscenarier kan utföras pÄ konstant tid. I vÄr uppgift finns det inget explicit krav pÄ att fÄ en lista över alla anvÀndarens vÀnner, men i verkliga projekt skulle det vara bra för oss som analytiker att "förespegla" att en sÄdan uppgift kan uppstÄ och "steka halm", sÄ att sÀga. DÀrför lutar jag Ät alternativ 3. Men det Àr fullt möjligt att detta krav i ett verkligt projekt redan har lösts med andra medel, sÄ utan en övergripande förstÄelse av hela uppgiften bör man inte dra nÄgra definitiva slutsatser.

Förberedelse av experimentet

De ovanstĂ„ende teoretiska resonemangen skulle vi vilja pröva i praktiken – och det var mĂ„let med den idĂ© som uppstod under de lĂ„nga helgerna. För detta behöver vi bedöma hastigheten pĂ„ vĂ„rt "hypotetiska program" i alla de beskrivna anvĂ€ndarscenarierna samt hur denna tid ökar med storleken pĂ„ det sociala nĂ€tverket (n). Den mĂ„lparameter vi Ă€r intresserade av och som vi kommer att mĂ€ta under experimentet Ă€r den tid som det "hypotetiska programmet" lĂ€gger pĂ„ att utföra en "affĂ€rsoperation". Med "affĂ€rsoperation" menar vi en av följande:

  • LĂ€gga till en ny vĂ€n
  • Kontrollera om anvĂ€ndare A Ă€r vĂ€n med anvĂ€ndare B
  • Ta bort en vĂ€n

SÄledes, med hÀnsyn till de krav som angivits i den ursprungliga uppgiften, framtrÀder följande scenario för kontroll:

  • Skriva data. Generera slumpmĂ€ssigt ett ursprungligt nĂ€tverk av storlek n. För att nĂ€rma oss "verkliga vĂ€rlden" Ă€r antalet vĂ€nner per anvĂ€ndare ocksĂ„ en slumpmĂ€ssig variabel. MĂ€t tiden som vĂ„rt "hypotetiska program" tar för att skriva alla genererade data i HBase. Dela sedan den uppmĂ€tta tiden med det totala antalet tillagda vĂ€nner – sĂ„ fĂ„r vi den genomsnittliga tiden för en "affĂ€rsoperation".
  • LĂ€sa data. För varje anvĂ€ndare skapa en lista över
  • Borttagning av data. Ta bort alla vĂ€nskapsförbindelser för anvĂ€ndaren. Borttagningsordningen ska vara slumpmĂ€ssig (det vill sĂ€ga

Scenarierna mÄste köras för varje av de fem modellerna för data och för olika storlekar av sociala nÀtverk, för att se hur tiden förÀndras med dess tillvÀxt. Inom varje n-lÀnk i nÀtverket och listan över anvÀndare för kontroll mÄste, naturligtvis, vara desamma för alla fem varianter.
För bÀttre förstÄelse, nedan ger jag ett exempel pÄ genererade data för n= 5. Den skrivna "generatorn" ger ut tre ordböcker med ID:n:

  • den första - för insĂ€ttning
  • den andra - för kontroll
  • den tredje - för borttagning

{0: [1], 1: [4, 5, 3, 2, 1], 2: [1, 2], 3: [2, 4, 1, 5, 3], 4: [2, 1]} # totalt 15 vÀnner

{0: [1, 10800], 1: [5, 10800, 2, 10801, 4, 10802], 2: [1, 10800], 3: [3, 10800, 1, 10801, 5, 10802], 4: [2, 10800]} # totalt 18 kontrollerade subjekt

{0: [1], 1: [1, 3, 2, 5, 4], 2: [1, 2], 3: [4, 1, 2, 3, 5], 4: [1, 2]} # totalt 15 vÀnner

Som man kan se, alla ID:n större Àn 10 000 i ordboken för kontroll Àr just de som med sÀkerhet kommer att ge svaret False. InsÀttning, kontroll och borttagning av "vÀnner" genomförs precis i den ordning som anges i ordboken.

Experimentet genomfördes pĂ„ en bĂ€rbar dator som kör Windows 10, dĂ€r en Docker-container körde en HBase-databas, medan en annan körde Python med Jupyter Notebook. Docker tilldelades 2 CPU-kĂ€rnor och 2 GB RAM. All logik, bĂ„de emuleringen av "det hypotetiska programmet" och "infrastrukturen" för att generera testdata och mĂ€ta tid skrevs i Python. För att arbeta med HBase anvĂ€ndes biblioteket happybase, för att berĂ€kna hashvĂ€rden (MD5) för alternativ 5 – hashlib

Med hĂ€nsyn till den specifika bĂ€rbar datorns berĂ€kningskraft valdes experimentellt starten för n = 10, 30, 
. 170 – nĂ€r den totala tiden för hela testcykeln (alla scenarier för alla alternativ för alla n) fortfarande var mer eller mindre rimlig och fick plats under en kopp te (i genomsnitt 15 minuter).

HĂ€r mĂ„ste jag pĂ„peka att vi i detta experiment frĂ€mst bedömer inte absoluta prestationstal. Även en relativ jĂ€mförelse mellan de tvĂ„ olika alternativen kan vara nĂ„got otillförlitlig. Just nu Ă€r vi intresserade av hur tiden förĂ€ndras beroende pĂ„ n, eftersom det med hĂ€nsyn till den ovan nĂ€mnda konfigurationen av "testbĂ€nken" Ă€r mycket svĂ„rt att fĂ„ tidsuppskattningar som Ă€r "rensade" frĂ„n pĂ„verkan av slumpmĂ€ssiga och andra faktorer (och ett sĂ„dant mĂ„l har inte stĂ€llts).

Experimentresultatet

Det första testet – hur tiden som anvĂ€nds för att fylla i vĂ€nlistan förĂ€ndras. Resultatet – i diagrammet nedan.
Designprinciper för datamodellen för NoSQL
Alternativen 3-5 visar som förvÀntat praktiskt konstant tid för "affÀrsoperationen", som inte beror pÄ nÀtverksstorlekens tillvÀxt och ingen mÀrkbar skillnad i prestanda.
Alternativ 2 visar ocksĂ„ konstant, men nĂ„got sĂ€mre prestanda, nĂ€stan exakt 2 gĂ„nger jĂ€mfört med alternativen 3-5. Detta Ă€r glĂ€djande, eftersom det stĂ€mmer överens med teorin – i detta alternativ Ă€r antalet in- och utdataoperationer till/frĂ„n HBase faktiskt 2 gĂ„nger fler. Detta kan fungera som indirekt bevis pĂ„ att vĂ„r testbĂ€nk i grunden ger en hyfsad noggrannhet.
Alternativ 1 visar sig ocksÄ vara det lÄngsammaste och demonstrerar en linjÀr ökning av tiden som krÀvs för att lÀgga till en vÀn i takt med nÀtverksstorleken.
LÄt oss nu titta pÄ resultaten frÄn det andra testet.
Designprinciper för datamodellen för NoSQL
Alternativen 3-5 uppför sig förutsĂ€gbart – konstant tid som inte beror pĂ„ nĂ€tverksstorleken. Alternativen 1 och 2 visar en linjĂ€r ökning av tiden nĂ€r nĂ€tverksstorleken ökar och liknande prestanda. Alternativ 2 Ă€r dock nĂ„got lĂ„ngsammare – uppenbarligen pĂ„ grund av behovet av att lĂ€sa och bearbeta den extra kolumnen "count", vilket blir mer mĂ€rkbart nĂ€r n ökar. Men jag avstĂ„r Ă€ndĂ„ frĂ„n att dra nĂ„gra slutsatser, eftersom noggrannheten i denna jĂ€mförelse Ă€r relativt lĂ„g. Dessutom varierade dessa relationer (vilket alternativ, 1 eller 2, Ă€r snabbare) frĂ„n körning till körning (medan de upprĂ€tthöll karaktĂ€ren av beroendeförhĂ„llandet och "gick nĂ€sa vid nĂ€sa").

Och den sista grafen – resultatet av borttagningstestet.

Designprinciper för datamodellen för NoSQL

HÀr Àr det Äterigen utan överraskningar. Alternativen 3-5 utför borttagning pÄ konstant tid.
Fascinerande nog visar alternativ 4 och 5, till skillnad frÄn de tidigare scenarierna, nÄgot sÀmre prestanda Àn alternativ 3. Uppenbarligen Àr borttagning av en rad mer kostsam Àn borttagning av en kolumn, vilket Àr logiskt.

Alternativen 1 och 2 visar förutsĂ€gbart en linjĂ€r ökning av tiden. Dessutom Ă€r alternativ 2 konsekvent lĂ„ngsammare Ă€n alternativ 1 – pĂ„ grund av den extra in- och utmatningsoperationen för "underhĂ„ll" av kolumnen count.

AllmÀnna slutsatser frÄn experimentet:

  • Alternativen 3-5 visar högre effektivitet eftersom de utnyttjar fördelarna med HBase; deras prestanda skiljer sig Ă„t med en konstant och beror inte pĂ„ nĂ€tverksstorleken.
  • Skillnaden mellan alternativen 4 och 5 registrerades inte. Men det betyder inte att alternativ 5 inte bör anvĂ€ndas. Det Ă€r fullt möjligt att det experimentella scenariot, med hĂ€nsyn till testbĂ€nkes specifikationer, inte möjliggjorde att den skulle identifieras.
  • KaraktĂ€ren av tidstillvĂ€xten för "affĂ€rsoperationer" med data bekrĂ€ftade i stort sett tidigare teoretiska slutsatser för alla alternativ.

Epilog

Genomförda grova experiment bör inte betraktas som absolut sanning. Det finns flera faktorer som inte har beaktats och som förvrĂ€nger resultaten (sĂ€rskilt tydligt synligt i graferna vid smĂ„ nĂ€tverksstorlekar). Till exempel hastigheten pĂ„ thrift som anvĂ€nds av happybase, mĂ€ngden och sĂ€ttet för implementationen av logiken som jag hade skrivit i Python (jag pĂ„stĂ„r inte att koden var skriven optimalt och nyttjade alla komponenters kapabiliteter effektivt), eventuella egenskaper av HBase-cache, bakgrundsaktiviteter pĂ„ Windows 10 pĂ„ min bĂ€rbara dator osv. Övergripande kan man hĂ€vda att alla teoretiska utlĂ€ggningar experimentellt visade sin giltighet. Eller Ă„tminstone gick det inte att motbevisa dem med ett sĂ„dant "rakt angrepp".

Till sist - rekommendationer till alla som just börjat designa datamodeller i HBase: abstrahera utifrÄn tidigare erfarenheter med relationsdatabaser och kom ihÄg "budorden":

  • NĂ€r vi designar, utgĂ„r vi frĂ„n uppgiften och mönster för datamanipulation, inte frĂ„n modellen för Ă€mnesomrĂ„det.
  • Effektiv Ă„tkomst (utan fullstĂ€ndig tabellskanning) – endast via nyckel.
  • Deniormalisering.
  • Olika rader kan innehĂ„lla olika kolumner.
  • Dynamiskt kolumninnehĂ„ll.

KĂ€lla: habr.com

Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar đŸ”„ Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster