Kuidas töötavad relatsioonilised andmebaasid (Osa 1)

Tere, Habr! Esitan teile artikli tÔlke
"Kuidas toimib relaatsiooniline andmebaas".

Relaatsiooniliste andmebaaside kohta mĂ”eldes ei saa ma jĂ€tta mĂ”tlemata, et midagi on puudu. Need on kasutusel igal pool. On palju erinevaid andmebaase: alates vĂ€ikesest ja kasulikust SQLite'ist kuni vĂ”imsa Teradatani. Kuid neid, mis selgitavad, kuidas andmebaas töötab, on vaid mĂ”ned artiklid. Saate ise otsida 'howdoesarelationaldatabasework' ("kuidas töötavad relaatsioonilised andmebaasid") ja nĂ€ha, kui vĂ€he tulemusi seal on. Veelgi enam, need artiklid on lĂŒhikesed. Kui aga otsite viimaseid moetehnoloogiaid (Big Data, NoSQL vĂ”i JavaScript), leiate rohkem sĂŒvitsi minevaid artikleid, mis selgitavad, kuidas need töötavad.

Kas relaatsioonilised andmebaasid on liiga vanad ja igavad, et neid saaks selgitada vĂ€ljaspool ĂŒlikooli kursusi, uurimistöid ja raamatuid?

Kuidas töötavad relatsioonilised andmebaasid (Osa 1)

Arendajana vihkan ma kasutada seda, mida ma ei mĂ”ista. Ja kui andmebaase on kasutatud rohkem kui 40 aastat, peab olema pĂ”hjus. Nende aastate jooksul olen kulutanud sadu tunde, et tĂ”eliselt mĂ”ista neid kummalisi musti kaste, mida kasutan iga pĂ€ev. Seotud andmebaasid on vĂ€ga huvitavad, kuna need pĂ”hineb kasulikul ja korduvalt kasutataval kontseptsioonil. Kui teid huvitab andmebaasi mĂ”istmine, kuid teil ei ole kunagi olnud aega vĂ”i soovi selle ulatuslikku teemat sĂŒveneda, siis see artikkel peaks teile meeldima.

Kuigi selle artikli pealkiri on selge, ei ole selle artikli eesmĂ€rgiks andmebaasi kasutamine. SeetĂ”ttu peate juba teadma, kuidas kirjutada lihtne ĂŒhendusloend ja pĂ”hilised pĂ€ringud CRUD; vastasel juhul ei pruugi te seda artiklit mĂ”ista. See on ainus, mida peate teadma; ma selgitan kĂ”ike muud.

Alustan mĂ”ningatest arvutiteaduse alustest, nagu algoritmide ajakompleksus (BigO). Tean, et mĂ”ned teist ei salli seda kontseptsiooni, kuid ilma selleta ei mĂ”ista te andmebaasi sisemisi nĂŒansse. Kuna see on tohutu teema, fokuseerin sellele, mida pean oluliseks: kuidas andmebaas töötleb SQL palve. Esitan ainult pĂ”hialused andmebaasidest, et artikli lĂ”pus oleks teil ettekujutus sellest, mis toimub sisemiselt.

Kuna see on pika- ja tehnilise sisuga artikkel, mis sisaldab mitmeid algoritme ja andmestruktuure, Àrge kiirustage selle lugemisega. MÔned kontseptsioonid vÔivad olla keerulised ja te vÔite need vahele jÀtta, kuid ikkagi saada terviklikku arusaama.

Teie paremini informeerimiseks on see artikkel jagatud kolme ossa:

  • Andmebaasi madala ja kĂ”rge taseme komponentide ĂŒlevaade
  • KĂŒsimuste optimeerimise protsessi ĂŒlevaade
  • Tehingute ja vahemĂ€lupanga haldamise ĂŒlevaade

Tagasi alustesse

Aastaid tagasi (kaugelt, kaugelt galaktikast...) pidid arendajad tÀpselt teadma nende kodeeritud operatsioonide arvu. Nad teadsid oma algoritme ja andmestruktuure peast, sest ei saanud lubada endale aeglaste arvutite CPU ja mÀlu raiskamist.

Selles osas meenutan ma teile mÔningaid nendest kontseptsioonidest, kuna need on vajalikud andmebaasi mÔistmiseks. Tutvustan ka mÔistet andmebaasi indeks.

O(1) vs O(n2)

Praegu ei pööra paljud arendajad tÀhelepanu algoritmide ajakompleksusele... ja nad on Ôiged!

Kuid kui tegelete suuri andmemahtudega (ma ei rÀÀgi tuhandetest) vĂ”i kui vĂ”itlete millisekundite nimel, on ĂŒlioluline mĂ”ista seda kontseptsiooni. Ja nagu te aru saite, peavad andmebaasid tegelema mĂ”lema olukorraga! Ma ei pane teid kulutama rohkem aega, kui on vajalik selle olemuse mĂ”istmiseks. See aitab meil hiljem mĂ”ista kulu pĂ”hist optimeerimistkulu pĂ”histe optimeerimine).

Kontseptsioon

Algoritmi ajakompleksus kasutatakse selleks, et nÀha, kui palju aega kulub algoritmi tÀitmiseks antud andmemahu puhul.Selle kompleksuse kirjeldamiseks kasutatakse suurte O matemaatilisi tÀhistusi. See mÀrk on seotud funktsiooniga, mis kirjeldab, kui palju operatiivseid vajab algoritm mÀÀratud koguse sisendandmete töötlemiseks.

NĂ€iteks, kui ma ĂŒtlen "see algoritm on keerukus O (some_function() )", tĂ€hendab see, et teatud andmemahtu töötlemiseks on algoritmil vaja some_function(a_certain_amount_of_data) operatsiooni.

Samal ajal Oluline ei ole andmete hulk**, vaid see, ** kuidas operatsioonide arv kasvab koos andmehulga suurenemisega.. Aja keerukus ei nÀita tÀpset operatsioonide arvu, kuid see on hea viis tööaja hindamiseks.

Kuidas töötavad relatsioonilised andmebaasid (Osa 1)

Sellel graafikul nĂ€ete operatsioonide arvu sĂ”ltuvust sisendandmete mahust erinevat tĂŒĂŒpi algoritmide ajakeerukuse jaoks. Olen kasutanud logaritmilist skaalat nende kuvamiseks. TeisisĂ”nu, andmete hulk suureneb kiiresti 1-st kuni 1 miljardini. Saame nĂ€ha, et:

  • O(1) ehk konstantne keerukus jÀÀb muutumatuks (muul juhul ei saaks seda nimetada konstantseks keerukuseks).
  • O(log(n)) jÀÀb madalaks isegi miljardite andmete korral.
  • Halvim keerukus on O(n2), kus operatsioonide arv kasvab kiiresti.
  • Kahel teisel keerukusel on sama kiiresti suurenev jĂ”udlus.

NĂ€ited

VĂ€ikese andmehulga korral on O(1) ja O(n2) vahe tĂŒhine. Oletame nĂ€iteks, et teie algoritm peab töötlema 2000 elementi.

  • O(1) algoritm nĂ”uab 1 operatsiooni
  • O(log(n)) algoritm nĂ”uab 7 operatsiooni
  • O(n) algoritm nĂ”uab 2 000 operatsiooni
  • O(n * log(n)) algoritm nĂ”uab 14 000 operatsiooni
  • O(n2) algoritm nĂ”uab 4 000 000 operatsiooni

O(1) ja O(n2) erinevus vÔib tunduda suur (4 miljonit operatsiooni), kuid te kaotate maksimaalselt 2 ms, vaid silmapilguga. TÔepoolest, tÀnapÀeva protsessorid suudavad töödelda sadu miljoneid operatsioone sekundis. SeetÔttu ei ole jÔudlus ja optimeerimine paljude IT-projektide puhul probleem.

Nagu ma juba ĂŒtlesin, on selle mĂ”iste teadmine endiselt oluline, kui töötate suure hulga andmetega. Kui seekord peab algoritm töötlema 1 000 000 elementi (mis ei ole pĂ€ris palju andmebaasi jaoks):

  • O(1) algoritm nĂ”uab 1 operatsiooni
  • O(log(n)) algoritm nĂ”uab teilt 14 operatsiooni
  • O(n) algoritm nĂ”uab teilt 1 000 000 operatsiooni
  • O(n * log(n)) algoritm nĂ”uab teilt 14 000 000 operatsiooni
  • O(n2) algoritm nĂ”uab teilt 1 000 000 000 000 operatsiooni

Ma ei ole arvutusi teinud, kuid ma ĂŒtleksin, et O(n2) algoritmiga on teil aega kohvi juua (isegi kaks!). Kui lisate veel 0 andmete mahu juurde, on teil aega, et vĂ€ike uinak teha.

Minu sĂŒgavamale minek

Viidates:

  • Hea hajutustabeli otsimine leiab elemendi O(1) ajaga.
  • HĂ€sti tasakaalustatud puu otsimine annab tulemuse O(log(n)) ajaga.
  • Massiivis otsimine annab tulemuse O(n) ajaga.
  • Parimatel sortimisalgoritmidel on O(n * log(n)) keerukus.
  • Halb sĂŒsteemi sorteerimisalgoritm on keerukusega O(n2).

MÀrkus: jÀrgmistes osades nÀeme neid algoritme ja andmestruktuure.

Algoritmi ajakulu on mitut tĂŒĂŒpi:

  • keskmise juhtumi stsenaarium
  • parim arengusenaarium
  • ja halvim stsenaarium

Ajakulu on sageli halvim stsenaarium.

RÀÀkisin ainult algoritmi ajakulust, kuid keerukus kehtib ka:

  • algoritmi mĂ€lutarbimise kohta
  • algoritmi kettasisendi/vĂ€ljundi kohta

Muidugi on olemas keerukusi, mis on halvemad kui n2, nÀiteks:

  • n4: see on kohutav! MĂ”ned mainitud algoritmid on sellise keerukusega.
  • 3n: see on veel hullem! Üks algoritm, mida nĂ€eme selle artikli keskosas, omab seda keerukust (ja seda kasutatakse tĂ”epoolest paljudes andmebaasides).
  • faktoriaal n: te ei saa kunagi oma tulemusi isegi vĂ€ikse andmemahu korral.
  • nn: kui kohtate seda keerukust, peaksite endalt kĂŒsima, kas see tĂ”eliselt kuulub teie valdkonda 


MĂ€rkus: andsin teile mitte Ă”ige mÀÀratlemise tĂ€henduse „suur O”, vaid lihtsalt idee. Saate seda artiklit lugeda Vikipeediale reaalse (asĂŒmptootilise) mÀÀratlemise jaoks.

MergeSort (Merge Sort)

Mida teete, kui peate kogumit sorteerima? Mis? Te kutsute funktsiooni sort ()
 Okei, hea vastus
 Kuid andmebaasi puhul peate mĂ”istma, kuidas see sort () funktsioon töötab.

On mitmeid hĂ€id sorteerimisalgoritme, seega peatun kĂ”ige olulisemal: merge sort. VĂ”ib-olla te ei mĂ”ista, miks andmete sorteerimine on kasulik, kuid peaksite seda mĂ”istma pĂ€rast osakest, mis kĂ€sitleb pĂ€ringute optimeerimist. Veelgi enam, merge sort'i mĂ”istmine aitab meil hiljem mĂ”ista andmebaaside ĂŒldist operatsiooni join, mida nimetatakse merge liitu (merge join).

Merge (ĂŒhinemine)

Nagu paljude kasulike algoritmide puhul, pĂ”hineb merge sort nutikusel: 2 sorteeritud massiivi, mille suurus on N / 2, ĂŒhendamine N-elementseks sorteeritud massiiviks maksab vaid N toimingut. Seda toimingut nimetatakse ĂŒhinemiseks.

Vaatame, mida see lihtsa nÀite pÔhjal tÀhendab:

Kuidas töötavad relatsioonilised andmebaasid (Osa 1)

Selles joonises on nĂ€ha, et kahe 4-elementilise massiivi abil saate koostada lĂ”pliku jĂ€rjestatud 8-elementilise massiivi, tehes vaid ĂŒhe iteratsiooni. Kuna mĂ”lemad 4-elementilised massiivid on juba jĂ€rjestatud:

  • 1) vĂ”rrelge kahe massiivi jĂ”udmisel praeguseid elemente (alguses praegune = esimesele)
  • 2) seejĂ€rel vĂ”tke kĂ”ige vĂ€iksem, et paigutada see 8-elementilisse massiivi
  • 3) ja minge jĂ€rgmisele elemendile massiivis, kust te kĂ”ige vĂ€iksema elemendi vĂ”tsite
  • ja korrake 1, 2, 3, kuni jĂ”uate ĂŒhe massiivi viimase elemendini.
  • SeejĂ€rel vĂ”tate teise massiivi ĂŒlejÀÀnud elemendid, et paigutada need 8-elementilisse massiivi.

See töötab, sest mÔlemad 4-elementilised massiivid on jÀrjestatud ja seetÔttu ei pea te nendes massiivides 'tagasi minema'.

NĂŒĂŒd, kui oleme aru saanud sellest nippist, siin on minu pseudokood merge jaoks:

array mergeSort(array a)
   if(length(a)==1)
      return a[0];
   end if

   //rekursiivsed kÔned
   [left_array right_array] := split_into_2_equally_sized_arrays(a);
   array new_left_array := mergeSort(left_array);
   array new_right_array := mergeSort(right_array);

   // kahe vĂ€ikese jĂ€rjestatud massiivi ĂŒhendamine suureks
   array result := merge(new_left_array,new_right_array);
   return result;

Mergesort jagab ĂŒlesande vĂ€iksemateks ĂŒlesanneteks ning seejĂ€rel leiab vĂ€iksemate ĂŒlesannete tulemused, et saada algse ĂŒlesande tulemus (mĂ€rkus: seda tĂŒĂŒpi algoritme nimetatakse jagamiseks ja valitsuseks). Kui te ei saa seda algoritmi aru, Ă€rge muretsege; mina ei saanud ka esimesel korral aru. Kui see aitab, nĂ€en ma seda algoritmi kahefaasilise algoritmina:

  • Jagamisfaas, kus massiiv jagatakse vĂ€iksemateks massiivideks
  • Sorteerimisfaas, kus vĂ€iksed massiivid ĂŒhendatakse (kasutades ĂŒhendamist), et moodustada suurem massiiv.

Jagamisfaas

Kuidas töötavad relatsioonilised andmebaasid (Osa 1)

Jagamisetapis jagatakse massiiv ĂŒheĂŒksikuteks massiivideks 3 sammus. Formaalne sammaste arv on log(N) (kuna N=8, log(N) = 3).

Kust ma seda tean?

Ma olen geenius! ÜhesĂ”naga – matemaatika. Idee seisneb selles, et igal sammul jagatakse algse massiivi suurus 2. Sammaste arv on see, mitu korda saate algset massiivi kaheks jagada. See on logaritmi tĂ€pne mÀÀratlemine (alusel 2).

Sorteerimisfaas

Kuidas töötavad relatsioonilised andmebaasid (Osa 1)

Sorteerimisprotsessi alguses alustate ĂŒheinimeste (ĂŒheelemendiliste) massiividega. Iga etapi jooksul rakendate mitmeid sulandamiste operatsioone ning kogukulu on N = 8 operatsiooni:

  • Esimeses etapis on Teil 4 sulandumist, millest igaĂŒhe maksumus on 2 operatsiooni
  • Teises etapis on Teil 2 sulandumist, millest igaĂŒhe maksumus on 4 operatsiooni
  • Kolmandas etapis on Teil 1 sulandumine, mille maksumus on 8 operatsiooni

Kuna on olemas log(N) sammu, kogukulu N * log(N) operatsiooni.

Sulandmise sortimise eelised

Miks on see algoritm nii vÔimas?

Sest:

  • Saate seda muuta, et vĂ€hendada mĂ€lu kasutust, nii et Te ei loobu uutest massiividest, vaid muundate otse sisendmassii.

MĂ€rkus: seda tĂŒĂŒpi algoritmid nimetatakse in—place (sorteerimine ilma tĂ€iendava mĂ€luta).

  • Saate seda muuta, et kasutada ketta ruumi ja vĂ€ikest mĂ€lumahtu samal ajal ilma oluliste kettasisendite ja -vĂ€ljundita. Idee on laadida mĂ€llu ainult need osad, mida hetkel töödeldakse. See on oluline, kui peate sorteerima mitu gigabaiti andmeid ainult 100 megabaiti mĂ€lupuhvri mahuga.

MĂ€rkus: seda tĂŒĂŒpi algoritmid nimetatakse vĂ€line sortimine.

  • Saate seda muuta, et see töötaks mitme protsessi / joone / serveriga.

NĂ€iteks jaotatud sulatussortimine on ĂŒks peamisi komponente Hadoop (mis on struktureeritud suurtes andmetes).

  • See algoritm suudab muuta pliidi kullaks (tĂ”siselt!).

Seda sortimisalgoritmi kasutatakse enamikus (kui mitte kÔigis) andmebaasides, kuid see pole ainus. Kui soovite rohkem teada, vÔite lugeda seda uurimistööd, mis arutleb andmebaasi tavaliste sortimisalgoritmide plusse ja miinuseid.

Massiiv, Puud ja Hash-tabel

NĂŒĂŒd, kui me mĂ”istame ajalisest keerukusest ja sorteerimisest, pean ma teile rÀÀkima kolmest andmestruktuurist. See on oluline, kuna need moodustavad tĂ€napĂ€evaste andmebaaside aluse.Tutvustan ka mĂ”istet andmebaasi indeks.

MaatrikssĂŒsteem

KahemÔÔtmeline massiiv on kÔige lihtsam andmestruktuur. Tabelit vÔib kÀsitleda kui massiivi. NÀiteks:

Kuidas töötavad relatsioonilised andmebaasid (Osa 1)

See 2-mÔÔtmeline massiiv esindab tabelit ridade ja veergudega:

  • Iga rida esindab mingit entiteeti.
  • Veergudes hoitakse omadusi, mis kirjeldavad entiteeti.
  • Iga veerg hoiab andmeid kindlas tĂŒĂŒbis (tĂ€isarv, string, kuupĂ€ev 
).

Kuigi on mugav andmeid hoida ja visualiseerida, ei sobi see, kui peate leidma kindla vÀÀrtuse.

NĂ€iteks, kui soovite leida kĂ”iki tĂŒĂŒpe, kes töötavad Suurbritannias, peate iga rida lĂ€bi vaatama, et mÀÀrata, kas see rida kuulub Suurbritanniale. See maksab teile N operatsiooni, kus N — ridade arv, mis on suhteliselt hea, kuid kas on kiiremat teed? NĂŒĂŒd on aeg tutvuda puude struktureerimisega.

MÀrkus: enamik tÀnapÀevaseid andmebaase pakuvad ulatuslikke massiive tÔhusaks tabelite salvestamiseks: heap-organiseeritud tabelid ja indeksiga organiseeritud tabelid. Kuid see ei muuda kiire otsingu probleemi teatud tingimuste jaoks veergude grupis.

Andmebaasi puu ja indeks

Binaarne otsingupuu on binaarne puu, millel on eriline omadus: iga sÔlme vÔtme peab olema:

  • suurem kui kĂ”ik vĂ”tmed, mis on salvestatud vasakusse alampuusse
  • vĂ€iksem kui kĂ”ik vĂ”tmed, mis on salvestatud paremasse alampuusse

Vaatame, mida see visuaalselt tÀhendab

Idee

Kuidas töötavad relatsioonilised andmebaasid (Osa 1)

See puu sisaldab N = 15 elementi. Oletame, et otsin 208:

  • Alustan juurest, mille vĂ”tme vÀÀrtus on 136. Kuna 136 < 208, vaatan sĂ”lme 136 paremat alampuud.
  • 398 > 208, seetĂ”ttu vaatan sĂ”lme 398 vasakut alampuud
  • 250 > 208, seetĂ”ttu vaatan sĂ”lme 250 vasakut alampuud
  • 200 < 208, seetĂ”ttu vaatan sĂ”lme 200 paremat alampuud. Kuid 200-l ei ole paremat alampuud, vÀÀrtust ei eksisteeri (sest kui see eksisteeriks, oleks see sĂ”lme 200 paremas alampuus).

NĂŒĂŒd oletame, et otsin 40

  • Alustan juurest, mille vĂ”tme vÀÀrtus on 136. Kuna 136 > 40, vaatan sĂ”lme 136 vasakut alampuud.
  • 80 > 40, seega vaatan ma_node 80 vasakut alampuud
  • 40= 40, node eksisteerib. TĂ”stan vĂ€lja rea ID selle sĂ”lme sees (seda pole joonisel) ning otsin selle rea ID pĂ”hjal tabelist.
  • Rea ID teadmine vĂ”imaldab mul teada, kus andmed tabelis asuvad, ja seetĂ”ttu saan neid kohe kĂ€tte.

KokkuvÔttes maksavad mÔlemad otsingud mulle tasemeid puu sees. Kui loete hoolikalt sulandumisjÀrjestuse osa, peaksite nÀgema, et siin on log (N) taset. Seega, otsingu maksumus log(N), mitte paha!

Naaseme meie probleemile

Aga see on vÀga abstraktne, seega naeme meie probleemile. Selle asemel et lihtsalt terve arvu, kujutage ette stringi, mis esindab kellegi riiki eelnevas tabelis. Eeldame, et teil on puu, mis sisaldab vÀlja "country" (veeru 3) tabelist:

  • Kui soovite teada, kes töötab Ühendkuningriigis
  • vaatate puu suunas, et leida sĂ”lm, mis esindab Ühendkuningriiki
  • sĂ”lmes "UKnode" leiate Ühendkuningriigi töötajate salvestuste asukoha.

See otsing maksab log(N) toimingut, mitte N toimingut, kui te ei kasuta otse massiivi. Just see, mida te tutvustasite — oli andmebaasi indeks.

Sa saad luua indeksipuu mistahes vĂ€ljade rĂŒhma jaoks (string, number, 2 stringi, number ja string, kuupĂ€ev
) seni, kuni sul on vĂ”rdlemiseks funktsioon (st vĂ€ljade rĂŒhm), et saaksid kehtestada jĂ€rjestuse vĂ”tmete vahel (mis kehtib kĂ”igi pĂ”hityĂŒpide kohta andmebaasis).

B+TreeIndex

Kuigi see puu töötab hĂ€sti kindla vÀÀrtuse saamiseks, on olemas SUUR probleem, kui sul on vaja saada mitu elementi kahe vÀÀrtuse vahel. See maksab O(N), kuna sul tuleb iga puu sĂ”lm lĂ€bi vaadata ja kontrollida, kas see on nende kahe vÀÀrtuse vahel (nĂ€iteks jĂ€rjestatud puu lĂ€bimise kaudu). Veelgi enam, see operatsioon ei sobi diskivĂ”imalustele, kuna sul tuleb lugeda terve puu. Peame leidma viisi, kuidas tĂ”husalt teostada vahe-kĂŒsimust. Selle probleemi lahendamiseks kasutavad kaasaegsed andmebaasid muutatud versiooni varasemast puust nimega B+Tree. B+Tree puus:

  • ainult kĂ”ige alumised sĂ”lmed (lehed) hoidvad teavet (ridade asukoht seotud tabelis)
  • ĂŒlejÀÀnud sĂ”lmed asuvad siin Ă”ige sĂ”lme suunamiseks otsimise ajal Kuidas nĂ€ete, on siin rohkem sĂ”lmi (kaks korda rohkem). TĂ”epoolest, teil on lisasĂ”lmed, „otsuste tegemise sĂ”lmed“, mis aitavad teil leida Ă”ige sĂ”lme (mis hoiab ridade asukohta seotud tabelis). Kuid otsingu keerukus on endiselt O(log(N)) (seal on vaid veel ĂŒks tase). Suur vahe seisneb selles, et.

Kuidas töötavad relatsioonilised andmebaasid (Osa 1)

Nagu nĂ€ete, on siin rohkem sĂ”lme (kahe korra vĂ”rra). TĂ”eliselt, teil on lisasĂ”lmed, "otsustuspunktid", mis aitavad teil leida Ă”ige sĂ”lm (mis hoiab seostatud tabeli ridade asukohta). Kuid otsingu keerukus on endiselt O(log(N)) (olemas on vaid veel ĂŒks tase). Suur erinevus seisneb selles, et alumise taseme sĂ”lmed on seotud oma jĂ€reltulijatega..

Selle B+Tree puhul, kui otsite vÀÀrtusi vahemikus 40 kuni 100:

  • Peate lihtsalt otsima 40 (vĂ”i lĂ€himat vÀÀrtust, kui 40 ei eksisteeri), nagu te tegite varasema puuga.
  • SeejĂ€rel koguge 40 jĂ€reltulijad, kasutades otseseid viiteid jĂ€reltulijatele, kuni jĂ”uate 100.

Oletame, et leidsid M jÀrglast ja puul on N sÔlme. Konkreetse sÔlme leidmine maksab log(N) nagu eelmises puus. Kuid kui oled saanud selle sÔlme, saad M jÀrglast M operatsiooni kaudu viidete juurde. See otsing maksab ainult M+log(N) operatsiooni, vÔrreldes N operatsiooniga eelmises puus. Veelgi enam, sul ei ole vaja lugeda kogu puu (ainult M + log(N) sÔlme), mis tÀhendab vÀiksemat ketta kasutust. Kui M on vÀike (nÀiteks 200 rida) ja N suur (1 000 000 rida), on see SUUREM erinevus.

Aga siin on uusi probleeme (taas!). Kui lisad vÔi eemaldad rea andmebaasis (ja seega seotud indeksis B+Tree):

  • pead sĂ€ilitama jĂ€rjekorra sĂ”lmede vahel B+Tree-s, vastasel juhul ei saa sa leida sĂ”lme sorteerimata puus.
  • pead hoidma minimaalset vĂ”imalikku tasemete arvu B+Tree-s, vastasel juhul muutub ajakulu O(log(N))-st O(N)-ks.

TeisisĂ”nu, B+Tree peab olema isekorrastuv ja tasakaalustatud. Õnneks on see vĂ”imalik nutikate kustutamis- ja sisestamisoperatsioonidega. Kuid see on kulukas: sisestamine ja kustutamine B+ puus maksavad O(log(N)). SellepĂ€rast olete vĂ”ib-olla kuulnud, et liigne indeksite kasutamine ei ole hea mĂ”te. TĂ”epoolest, te aeglustate kiiret sisestamist / vĂ€rskendamist / kustutamist tabelis, kuna andmebaasis tuleb iga indeksi jaoks lĂ€bi viia kulukas O(log(N)) operatsioon indeksi uuendamiseks. Veelgi enam, indeksite lisamine tĂ€hendab suuremat koormust tehingute haldurile (sellest rÀÀgitakse artikli lĂ”pus).

Kuna soovite rohkem teavet, saate vaadata Vikipeedia artiklit B+Puu. Kui soovite nÀidet B+Tree rakendamisest andmebaasis, vaadake selle artikli ja selle artikli maailmakuulsa MySQL arendaja juhendit. Need keskenduvad sellele, kuidas InnoDB (MySQL mootor) indekseid haldab.

MĂ€rkus: lugeja ĂŒtles mulle, et madala taseme optimeerimiste tĂ”ttu peab B+ puu olema tĂ€ielikult tasakaalustatud.

HashTable (RĂ€si-tabel)

Meie viimane oluline andmestruktuur on hash-tabel. See on vĂ€ga kasulik, kui soovite kiiresti vÀÀrtusi otsida. Veelgi enam, hash-tabeli mĂ”istmine aitab meil hiljem mĂ”ista ĂŒldoperatsiooni, millega ĂŒhendatakse andmebaas, tuntud kui hash-ĂŒhendus ( hash join). See andmestruktuur on samuti andmebaasi sees mĂ”ningate sisestruktuuride (nĂ€iteks lukutabel vĂ”i puuderiit, me nĂ€eme mĂ”lemat neist kontseptsioonidest hiljem).

Hash-tabel on andmestruktuur, mis leiab elemendi kiiresti selle vÔtme jÀrgi. Hash-tabeli ehitamiseks peate mÀÀrama:

  • vĂ”tme oma elementide jaoks
  • hash-funktsiooni vĂ”tmete jaoks. Arvutatud vĂ”tmehassed annavad elementide asukoha (mida nimetatakse segmendiks ).
  • vĂ”tmete vĂ”rdlemise funktsiooni. Kui olete leidnud Ă”ige segmendi, peate leidma elemendi, mida otsite, segmendi sees, kasutades seda vĂ”rdlust.

Lihtne nÀide

VÔtame visuaalse nÀite:

Kuidas töötavad relatsioonilised andmebaasid (Osa 1)

See hash-tabelil on 10 segmenti. Kuna ma olen laisk, olen kujutanud vaid 5 segmenti, kuid tean, et olete nutikad, seega lasen teil ise 5 teist segmenti ette kujutada. Kasutasin vÔtme 10-modulo hash-funktsiooni. TeisisÔnu, hoian alles ainult elemendi vÔtme viimast numbrit, et leida selle segment:

  • kui viimane number on 0, siis element kuulub segmenti 0,
  • kui viimane number on 1, siis element kuulub segmenti 1,
  • kui viimane number on 2, siis element kuulub segmendi 2,
  • 


Kasutatud vÔrdlev funktsioon on lihtsalt tÀisarvude vÔrdlemine.

Oletame, et soovite saada elementi 78:

  • Hash-tabel arvutab 78 jaoks hash-koodi, mis on 8.
  • Hash-tabel vaatab segmenti 8 ja esimene element, mille ta leiab, on 78.
  • See tagastab teile elemendi 78
  • Otsing maksab ainult 2 operatsiooni (ĂŒks hash-funktsiooni vÀÀrtuse arvutamiseks ja teine elementide otsimiseks segmendis).

NĂŒĂŒd oletame, et soovite saada elementi 59:

  • Hash-tabel arvutab 59 jaoks hash-koodi, mis on 9.
  • HĂ€sti laotud tabel otsib 9. segmendis, esimene leitud element on 99. Kuna 99!=59, pole 99 Ă”ige element.
  • Sama loogikat kasutades vĂ”etakse teine element (9), kolmas (79), 
, viimane (29).
  • Elementi ei leitud.
  • Otsing maksis 7 operatsiooni..

Hea hash-funktsioon.

Nagu nÀete, sÔltub otsitava vÀÀrtuse pÔhjal hind erinev!

Kui ma nĂŒĂŒd muudan hash-funktsiooni modulaarselt 1 000 000 vĂ”tme jĂ€rgi (st vĂ”tan viimased 6 numbrit), siis teine otsing maksab ainult 1 operatsiooni, kuna segmendis 000059 pole elemente. Reaalne ĂŒlesanne on leida hea hash-funktsioon, mis loob segmente, mis sisaldavad vĂ€ga vĂ€he elemente..

Minu nÀites on hea hash-funktsiooni leidmine lihtne. Kuid see on lihtne nÀide, hea hash-funktsiooni leidmine on keerulisem, kui vÔti on:

  • string (nt perekonnanimi)
  • 2 stringi (nt perekonnanimi ja eesnimi)
  • 2 stringi ja kuupĂ€ev (nt perekonnanimi, eesnimi ja sĂŒnnipĂ€ev)
  • 


Hea hash-funktsiooniga toimub otsing hash-tabelis O(1) ajal..

Massiiv vs hash-tabel.

Miks mitte kasutada massiivi?

Hmm, hea kĂŒsimus.

  • Hash-tabel vĂ”ib olla. osaliselt mĂ€lu koormatud., ja ĂŒlejÀÀnud segmendid vĂ”ivad jÀÀda kettale.
  • Massiivi jaoks peate kasutama jĂ€rjepidevat mĂ€luruumi. Kui laadite sisse suure tabeli, on vĂ€ga raske leida piisavalt jĂ€rjepidevat ruumi..
  • Hash-tabeli jaoks saate valida vajaliku vĂ”tme (nĂ€iteks isiku riik ja perekonnanimi).

Lisainformatsiooni saamiseks vÔite lugeda artiklit JavaHashMap, mis on efektiivne hash-tabeli rakendus; te ei pea Java't mÔistma, et mÔista artiklis esitatud mÔisteid.

Allikas: habr.com

Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid đŸ”„ Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster