Kā darbojas relāciju datu bāzes (1. daļa)

Čau Habr! Piedāvāju jūsu uzmanībai raksta tulkojumu
"Kā darbojas relāciju datubāze".

Runājot par relāciju datu bāzēm, es nevaru palÄ«dzēt, bet domāju, ka kaut kā trÅ«kst. Tos izmanto visur. Ir pieejamas daudzas dažādas datu bāzes, sākot no mazās un noderÄ«gās SQLite lÄ«dz jaudÄ«gajai Teradata. Bet ir tikai daži raksti, kas izskaidro, kā darbojas datubāze. Varat meklēt sevi, izmantojot ā€œhowdoesarelationaldatabaseworkā€, lai redzētu, cik maz ir rezultātu. Turklāt Å”ie raksti ir Ä«si. Ja meklējat jaunākās dinamiskās tehnoloÄ£ijas (BigData, NoSQL vai JavaScript), jÅ«s atradÄ«sit padziļinātus rakstus, kuros izskaidrots, kā tās darbojas.

Vai relāciju datu bāzes ir pārāk vecas un pārāk garlaicīgas, lai tās izskaidrotu ārpus universitātes kursiem, pētniecības darbiem un grāmatām?

Kā darbojas relāciju datu bāzes (1. daļa)

Kā izstrādātājam man nepatÄ«k izmantot kaut ko, ko nesaprotu. Un, ja datu bāzes ir izmantotas vairāk nekā 40 gadus, tam ir jābÅ«t iemeslam. Gadu gaitā esmu pavadÄ«jis simtiem stundu, lai patiesi izprastu Ŕīs dÄ«vainās melnās kastes, kuras lietoju katru dienu. Relāciju datu bāzes ļoti interesanti, jo viņi pamatojoties uz noderÄ«gām un atkārtoti lietojamām koncepcijām. Ja vēlaties izprast datubāzi, taču jums nekad nav bijis laika vai vēlmes iedziļināties Å”ajā plaÅ”ajā tēmā, jums vajadzētu izbaudÄ«t Å”o rakstu.

Lai gan Ŕī raksta nosaukums ir skaidrs, Ŕī raksta mērÄ·is nav saprast, kā izmantot datubāzi. Tāpēc jums jau vajadzētu zināt, kā uzrakstÄ«t vienkārÅ”u savienojuma pieprasÄ«jumu un pamata vaicājumus Neapstrādāts; pretējā gadÄ«jumā jÅ«s varat nesaprast Å”o rakstu. Tas ir vienÄ«gais, kas jums jāzina, pārējo es paskaidroÅ”u.

SākÅ”u ar dažiem datorzinātņu pamatiem, piemēram, algoritmu laika sarežģītÄ«bu (BigO). Es zinu, ka daži no jums ienÄ«st Å”o jēdzienu, taču bez tā jÅ«s nevarēsit saprast datubāzes sarežģījumus. Tā kā Ŕī ir milzÄ«ga tēma, Es koncentrÄ“Å”os uz kas, manuprāt, ir svarÄ«gi: kā datu bāze apstrādā SQL uzziņu. Es tikai iepazÄ«stināŔu datu bāzes pamatjēdzienilai raksta beigās jums bÅ«tu priekÅ”stats par to, kas notiek zem pārsega.

Tā kā Å”is ir garÅ” un tehnisks raksts, kas ietver daudz algoritmu un datu struktÅ«ru, veltiet laiku, lai to izlasÄ«tu. Dažus jēdzienus var bÅ«t grÅ«ti saprast; varat tos izlaist un joprojām gÅ«t vispārÄ«gu priekÅ”statu.

ZinoŔākiem jūsu vidū Ŕis raksts ir sadalīts 3 daļās:

  • Pārskats par zema un augsta lÄ«meņa datu bāzes komponentiem
  • Pārskats par vaicājumu optimizācijas procesu
  • Pārskats par darÄ«jumu un bufera pÅ«la pārvaldÄ«bu

Atgriezties uz pamatiem

Pirms gadiem (tālā, tālā galaktikā...) izstrādātājiem bija precīzi jāzina operāciju skaits, ko viņi kodēja. Viņi zināja savus algoritmus un datu struktūras no galvas, jo nevarēja atļauties tērēt savu lēno datoru CPU un atmiņu.

Å ajā daļā es jums atgādināŔu dažus no Å”iem jēdzieniem, jo ā€‹ā€‹tie ir bÅ«tiski datu bāzes izpratnei. Es arÄ« iepazÄ«stināŔu ar koncepciju datu bāzes indekss.

O(1) pret O(n2)

Mūsdienās daudziem izstrādātājiem nerūp algoritmu laika sarežģītība... un viņiem ir taisnība!

Bet, ja jums ir darÄ«Å”ana ar daudz datu (es nerunāju par tÅ«kstoÅ”iem) vai ja jums ir grÅ«tÄ«bas milisekundēs, ir ļoti svarÄ«gi saprast Å”o jēdzienu. Un, kā jÅ«s varat iedomāties, datu bāzēm ir jārisina abas situācijas! Es nelikÅ”u jums tērēt vairāk laika, nekā nepiecieÅ”ams, lai saprastu bÅ«tÄ«bu. Tas mums palÄ«dzēs izprast uz izmaksām balstÄ«tas optimizācijas jēdzienu vēlāk (izmaksāt pamatojoties optimizācija).

Jēdziens

Algoritma laika sarežģītÄ«ba izmanto, lai redzētu, cik ilgs laiks prasÄ«s algoritma pabeigÅ”anai noteiktam datu apjomam. Lai aprakstÄ«tu Å”o sarežģītÄ«bu, mēs izmantojam lielo O matemātisko apzÄ«mējumu. Å o apzÄ«mējumu izmanto kopā ar funkciju, kas apraksta, cik operāciju algoritmam nepiecieÅ”ams noteiktam ievades datu skaitam.

Piemēram, kad es saku "Å”im algoritmam ir sarežģītÄ«ba O(some_function())", tas nozÄ«mē, ka algoritmam ir nepiecieÅ”amas dažas_funkcijas(a_noteikts_datu_apjoms) darbÄ«bas, lai apstrādātu noteiktu datu apjomu.

Å ajā gadÄ«jumā, SvarÄ«gs nav datu apjoms**, citādi ** kā palielinās operāciju skaits, palielinoties datu apjomam. Laika sarežģītÄ«ba nenodroÅ”ina precÄ«zu darbÄ«bu skaitu, bet ir labs veids, kā novērtēt izpildes laiku.

Kā darbojas relāciju datu bāzes (1. daļa)

Šajā grafikā var redzēt operāciju skaitu pret ievades datu apjomu dažāda veida algoritmu laika sarežģītībām. Es izmantoju logaritmisko skalu, lai tos parādītu. Citiem vārdiem sakot, datu apjoms strauji palielinās no 1 līdz 1 miljardam. Mēs redzam, ka:

  • O(1) jeb konstanta sarežģītÄ«ba paliek nemainÄ«ga (citādi to nesauktu par konstantu sarežģītÄ«bu).
  • O(log(n)) joprojām ir zems pat ar miljardiem datu.
  • Sliktākās grÅ«tÄ«bas - O(n2), kur operāciju skaits strauji pieaug.
  • Pārējās divas komplikācijas palielinās tikpat ātri.

piemēri

Ar nelielu datu apjomu atŔķirÄ«ba starp O(1) un O(n2) ir niecÄ«ga. Piemēram, pieņemsim, ka jums ir algoritms, kuram jāapstrādā 2000 elementi.

  • O(1) algoritms jums izmaksās 1 operāciju
  • O(log(n)) algoritms jums izmaksās 7 operācijas
  • O(n) algoritms jums izmaksās 2 operāciju
  • Algoritms O(n*log(n)) tev izmaksās 14 000 operāciju
  • O(n2) algoritms jums izmaksās 4 000 000 operāciju

Å Ä·iet, ka atŔķirÄ«ba starp O(1) un O(n2) ir liela (4 miljoni darbÄ«bu), taču jÅ«s zaudēsiet ne vairāk kā 2 ms, tikai laiks pamirkŔķināt acis. PatieŔām, mÅ«sdienu procesori var apstrādāt simtiem miljonu operāciju sekundē. Tāpēc daudzos IT projektos veiktspēja un optimizācija nav problēma.

Kā jau teicu, joprojām ir svarÄ«gi zināt Å”o jēdzienu, strādājot ar milzÄ«gu datu apjomu. Ja Å”oreiz algoritmam ir jāapstrādā 1 000 000 elementu (kas datu bāzei nav tik daudz):

  • O(1) algoritms jums izmaksās 1 operāciju
  • O(log(n)) algoritms jums izmaksās 14 operācijas
  • O(n) algoritms jums izmaksās 1 000 000 operāciju
  • O(n*log(n)) algoritms jums izmaksās 14 000 000 operāciju
  • O(n2) algoritms jums izmaksās 1 000 000 000 000 operāciju

Es neesmu izdarījis matemātiku, bet es teiktu, ka ar O(n2) algoritmu jums ir laiks izdzert kafiju (pat divas!). Ja datu apjomam pievienosiet vēl 0, jums būs laiks pasnaust.

Iesim dziļāk

Par savu informāciju:

  • Laba hash tabulas uzmeklÄ“Å”ana atrod elementu O(1).
  • Meklējot labi lÄ«dzsvarotu koku, tiek iegÅ«ti rezultāti O(log(n)).
  • Meklējot masÄ«vā, rezultāti tiek iegÅ«ti O(n).
  • Labākajiem ŔķiroÅ”anas algoritmiem ir sarežģītÄ«ba O(n*log(n)).
  • Sliktam kārtoÅ”anas algoritmam ir sarežģītÄ«ba O(n2).

PiezÄ«me. Turpmākajās daļās mēs redzēsim Å”os algoritmus un datu struktÅ«ras.

Ir vairāki algoritmu laika sarežģītības veidi:

  • vidējais gadÄ«juma scenārijs
  • labākais scenārijs
  • un sliktākajā gadÄ«jumā

Laika sarežģītība bieži vien ir sliktākais scenārijs.

Es runāju tikai par algoritma laika sarežģītību, bet sarežģītība attiecas arī uz:

  • algoritma atmiņas patēriņŔ
  • diska I/O patēriņa algoritms

Protams, ir komplikācijas, kas ir sliktākas par n2, piemēram:

  • n4: tas ir briesmÄ«gi! Dažiem no minētajiem algoritmiem ir Ŕāda sarežģītÄ«ba.
  • 3n: tas ir vēl sliktāk! Vienam no algoritmiem, ko redzēsim Ŕī raksta vidÅ«, ir Ŕāda sarežģītÄ«ba (un to faktiski izmanto daudzās datu bāzēs).
  • faktoriāls n: jÅ«s nekad nesaņemsit rezultātus pat ar nelielu datu apjomu.
  • nn: Ja jÅ«s saskaraties ar Å”o sarežģītÄ«bu, jums vajadzētu pajautāt sev, vai tas tieŔām ir jÅ«su darbÄ«bas lauks...

Piezīme: es jums nesniedzu lielā O apzīmējuma faktisko definīciju, tikai ideju. Šo rakstu varat izlasīt vietnē Wikipedia reālajai (asimptotiskajai) definīcijai.

MergeSort

Ko jūs darāt, ja jums ir jākārto kolekcija? Kas? Jūs izsaucat funkciju sort()... Labi, laba atbilde... Bet datu bāzei ir jāsaprot, kā Ŕī sort() funkcija darbojas.

Ir vairāki labi ŔķiroÅ”anas algoritmi, tāpēc es koncentrÄ“Å”os uz vissvarÄ«gāko: sapludināt kārtot. JÅ«s, iespējams, nesaprotat, kāpēc datu kārtoÅ”ana Å”obrÄ«d ir noderÄ«ga, bet pēc vaicājuma optimizācijas daļas tas ir jādara. Turklāt sapludināŔanas kārtoÅ”anas izpratne palÄ«dzēs mums vēlāk izprast kopÄ«go datubāzes pievienoÅ”anās darbÄ«bu apvienot pievienoties (apvienoÅ”anās asociācija).

Apvienot

Tāpat kā daudzi noderīgi algoritmi, sapludināŔanas kārtoŔana balstās uz triku: 2 sakārtotu N/2 lieluma masīvu apvienoŔana N elementu sakārtotā masīvā maksā tikai N operācijas. Šo darbību sauc par apvienoŔanu.

ApskatÄ«sim, ko tas nozÄ«mē, izmantojot vienkārÅ”u piemēru:

Kā darbojas relāciju datu bāzes (1. daļa)

Šis attēls parāda, ka, lai izveidotu galīgo sakārtoto 8 elementu masīvu, jums tikai vienu reizi ir jāatkārto 2 4 elementu masīvi. Tā kā abi 4 elementu masīvi jau ir sakārtoti:

  • 1) jÅ«s salÄ«dzināt abus paÅ”reizējos elementus divos masÄ«vos (sākumā strāva = pirmais)
  • 2) pēc tam paņemiet mazāko, lai ievietotu to 8 elementu masÄ«vā
  • 3) un pārejiet uz nākamo elementu masÄ«vā, kurā paņēmāt mazāko elementu
  • un atkārtojiet 1,2,3, lÄ«dz sasniedzat viena masÄ«va pēdējo elementu.
  • Pēc tam ņemat pārējos cita masÄ«va elementus, lai ievietotu tos 8 elementu masÄ«vā.

Tas darbojas, jo abi 4 elementu masÄ«vi ir sakārtoti un tāpēc jums nav "jāatgriežas" Å”ajos masÄ«vos.

Tagad, kad mēs saprotam triku, Å”eit ir mans sapludināŔanas pseidokods:

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

   //recursive calls
   [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);

   //merging the 2 small ordered arrays into a big one
   array result := merge(new_left_array,new_right_array);
   return result;

SapludināŔanas kārtoÅ”ana sadala problēmu mazākās problēmās un pēc tam atrod mazāko problēmu rezultātus, lai iegÅ«tu sākotnējās problēmas rezultātu (piezÄ«me: Ŕāda veida algoritmu sauc par sadali un iekaro). Ja jÅ«s nesaprotat Å”o algoritmu, neuztraucieties; Es to nesapratu, kad pirmo reizi to redzēju. Ja tas var jums palÄ«dzēt, es redzu Å”o algoritmu kā divfāžu algoritmu:

  • SadalÄ«Å”anas fāze, kur masÄ«vs tiek sadalÄ«ts mazākos masÄ«vos
  • Å Ä·iroÅ”anas fāzē mazie masÄ«vi tiek apvienoti (izmantojot savienÄ«bu), lai izveidotu lielāku masÄ«vu.

SadalīŔanas fāze

Kā darbojas relāciju datu bāzes (1. daļa)

SadalīŔanas stadijā masīvs tiek sadalīts vienotos masīvos 3 soļos. Formālais soļu skaits ir log(N) (jo N=8, log(N) = 3).

Kā es to varu zināt?

Es esmu ģēnijs! Vārdu sakot - matemātika. Ideja ir tāda, ka katrs solis dala sākotnējā masīva lielumu ar 2. Soļu skaits ir skaits, cik reižu varat sadalīt sākotnējo masīvu divās daļās. Šī ir precīza logaritma definīcija (2. bāze).

ŠķiroŔanas fāze

Kā darbojas relāciju datu bāzes (1. daļa)

Å Ä·iroÅ”anas fāzē jÅ«s sākat ar vienotiem (viena elementa) masÄ«viem. Katrā darbÄ«bā tiek lietotas vairākas sapludināŔanas darbÄ«bas, un kopējās izmaksas ir N = 8 darbÄ«bas:

  • Pirmajā posmā jums ir 4 sapludināŔanas, kas katra maksā 2 darbÄ«bas
  • Otrajā darbÄ«bā jums ir 2 sapludināŔanas, kas katra maksā 4 darbÄ«bas
  • TreÅ”ajā darbÄ«bā jums ir 1 sapludināŔana, kas maksā 8 darbÄ«bas

Tā kā ir log(N) soļi, kopējās izmaksas N * log(N) operācijas.

ApvienoŔanas kārtoŔanas priekŔrocības

Kāpēc Å”is algoritms ir tik spēcÄ«gs?

Jo:

  • Varat to mainÄ«t, lai samazinātu atmiņas apjomu, lai jÅ«s neizveidotu jaunus masÄ«vus, bet gan tieÅ”i pārveidotu ievades masÄ«vu.

PiezÄ«me: Ŕāda veida algoritmu sauc inSākot novieta (ŔķiroÅ”ana bez papildu atmiņas).

  • Varat to mainÄ«t, lai vienlaikus izmantotu diska vietu un nelielu daudzumu atmiņas, neradot ievērojamas diska ievades/izvades izmaksas. Ideja ir ielādēt atmiņā tikai tās daļas, kuras paÅ”laik tiek apstrādātas. Tas ir svarÄ«gi, ja nepiecieÅ”ams kārtot vairāku gigabaitu tabulu tikai ar 100 megabaitu atmiņas buferi.

PiezÄ«me: Ŕāda veida algoritmu sauc ārējā ŔķiroÅ”ana.

  • Varat to mainÄ«t, lai tas darbotos vairākos procesos/pavedienos/serveros.

Piemēram, izplatÄ«tā sapludināŔanas kārtoÅ”ana ir viena no galvenajām sastāvdaļām Hadoop (kas ir lielo datu struktÅ«ra).

  • Å is algoritms var pārvērst svinu zeltā (tieŔām!).

Å is ŔķiroÅ”anas algoritms tiek izmantots lielākajā daļā (ja ne visās) datu bāzēs, taču tas nav vienÄ«gais. Ja vēlaties uzzināt vairāk, varat izlasÄ«t Å”o pētnieciskais darbs, kurā aplÅ«koti izplatÄ«to datu bāzu ŔķiroÅ”anas algoritmu plusi un mÄ«nusi.

Masīvu, koku un hash tabula

Tagad, kad mēs saprotam laika sarežģītÄ«bas un ŔķiroÅ”anas ideju, man vajadzētu pastāstÄ«t par 3 datu struktÅ«rām. Tas ir svarÄ«gi, jo viņi ir mÅ«sdienu datu bāzu pamatā. Es arÄ« iepazÄ«stināŔu ar koncepciju datu bāzes indekss.

Masīvs

Divdimensiju masÄ«vs ir vienkārŔākā datu struktÅ«ra. Tabulu var uzskatÄ«t par masÄ«vu. Piemēram:

Kā darbojas relāciju datu bāzes (1. daļa)

Å is 2 dimensiju masÄ«vs ir tabula ar rindām un kolonnām:

  • Katra rinda apzÄ«mē entÄ«tiju
  • Slejās tiek saglabāti rekvizÄ«ti, kas apraksta entÄ«tiju.
  • Katrā kolonnā tiek glabāti noteikta veida dati (vesels skaitlis, virkne, datums...).

Tas ir ērti datu glabāŔanai un vizualizÄ“Å”anai, taču, ja nepiecieÅ”ams atrast konkrētu vērtÄ«bu, tas nav piemērots.

Piemēram, ja vēlaties atrast visus vÄ«rieÅ”us, kuri strādā Apvienotajā Karalistē, jums ir jāaplÅ«ko katra rinda, lai noteiktu, vai Ŕī rinda pieder Apvienotajai Karalistei. Tas jums izmaksās N darÄ«jumusKur N - rindu skaits, kas nav slikti, bet vai var bÅ«t ātrāks veids? Tagad mums ir pienācis laiks iepazÄ«ties ar kokiem.

PiezÄ«me. Lielākā daļa mÅ«sdienu datu bāzu nodroÅ”ina paplaÅ”inātus masÄ«vus tabulu efektÄ«vai glabāŔanai: kaudzes sakārtotas tabulas un indeksu sakārtotas tabulas. Bet tas nemaina problēmu ātri atrast konkrētu nosacÄ«jumu kolonnu grupā.

Datu bāzes koks un indekss

Binārais meklÄ“Å”anas koks ir binārs koks ar Ä«paÅ”u Ä«paŔību, atslēgai katrā mezglā jābÅ«t:

  • lielāks nekā visas atslēgas, kas saglabātas kreisajā apakÅ”kokā
  • mazāk nekā visas atslēgas, kas saglabātas labajā apakÅ”kokā

Apskatīsim, ko tas nozīmē vizuāli

Ideja

Kā darbojas relāciju datu bāzes (1. daļa)

Šim kokam ir N = 15 elementi. Pieņemsim, ka es meklēju 208:

  • Es sāku no saknes, kuras atslēga ir 136. Tā kā 136<208, es skatos uz 136. mezgla labo apakÅ”koku.
  • 398>208 tāpēc es skatos uz 398. mezgla kreiso apakÅ”koku
  • 250>208 tāpēc es skatos uz 250. mezgla kreiso apakÅ”koku
  • 200<208, tāpēc es skatos uz mezgla 200 labo apakÅ”koku. Bet 200 nav labā apakÅ”koka, vērtÄ«ba neeksistē (jo, ja tas pastāv, tas bÅ«s labajā apakÅ”kokā 200).

Tagad pieņemsim, ka es meklēju 40

  • Es sāku no saknes, kuras atslēga ir 136. Tā kā 136 > 40, es skatos uz 136. mezgla kreiso apakÅ”koku.
  • 80 > 40, tāpēc es skatos uz 80. mezgla kreiso apakÅ”koku
  • 40 = 40, mezgls pastāv. Node iekÅ”pusē izgÅ«stu rindas ID (nav redzams attēlā) un tabulā meklēju doto rindas ID.
  • Zinot rindas ID, es varu precÄ«zi zināt, kur tabulā atrodas dati, lai es varētu tos izgÅ«t uzreiz.

Galu galā abi meklējumi man izmaksās koka iekÅ”ienē esoÅ”o lÄ«meņu skaitu. Ja uzmanÄ«gi izlasiet sadaļu par sapludināŔanas kārtoÅ”anu, jums vajadzētu redzēt, ka ir žurnāla (N) lÄ«meņi. Izrādās, meklÄ“Å”anas izmaksu žurnāls (N), nav slikti!

Atgriezīsimies pie mūsu problēmas

Bet tas ir ļoti abstrakti, tāpēc atgriezÄ«simies pie mÅ«su problēmas. VienkārÅ”a vesela skaitļa vietā iedomājieties virkni, kas attēlo kāda cilvēka valsti iepriekŔējā tabulā. Pieņemsim, ka jums ir koks, kurā ir tabulas lauks ā€œvalstsā€ (3. sleja):

  • Ja vēlaties uzzināt, kas strādā Apvienotajā Karalistē
  • paskatās uz koku, lai iegÅ«tu mezglu, kas apzÄ«mē Lielbritāniju
  • "UKnode" iekÅ”pusē jÅ«s atradÄ«siet Apvienotās Karalistes darbinieku ierakstu atraÅ”anās vietu.

Å Ä« meklÄ“Å”ana maksās log(N) operācijas, nevis N operācijas, ja izmantosit masÄ«vu tieÅ”i. Tas, ko jÅ«s tikko prezentējāt, bija datu bāzes indekss.

Varat izveidot indeksa koku jebkurai lauku grupai (virkne, numurs, 2 rindiņas, numurs un virkne, datums...), ja vien jums ir funkcija, lai salīdzinātu atslēgas (ti, lauku grupas), lai jūs varētu iestatīt secība starp atslēgām (kas attiecas uz visiem pamata tipiem datubāzē).

B+TreeIndex

Lai gan Å”is koks darbojas labi, lai iegÅ«tu noteiktu vērtÄ«bu, nepiecieÅ”amÄ«bas gadÄ«jumā pastāv LIELA problēma iegÅ«t vairākus elementus starp divām vērtÄ«bām. Tas maksās O(N), jo jums bÅ«s jāaplÅ«ko katrs koka mezgls un jāpārbauda, ā€‹ā€‹vai tas atrodas starp Ŕīm divām vērtÄ«bām (piemēram, ar sakārtotu koka ŔķērsoÅ”anu). Turklāt Ŕī darbÄ«ba nav draudzÄ«ga diskam I/O, jo jums ir jālasa viss koks. Mums ir jāatrod veids, kā efektÄ«vi izpildÄ«t diapazona pieprasÄ«jums. Lai atrisinātu Å”o problēmu, mÅ«sdienu datubāzēs tiek izmantota iepriekŔējā koka modificēta versija ar nosaukumu B+Tree. B+koka kokā:

  • tikai zemākie mezgli (lapas) uzglabāt informāciju (rindu atraÅ”anās vieta saistÄ«tajā tabulā)
  • pārējie mezgli ir Å”eit marÅ”rutÄ“Å”anai uz pareizo mezglu meklÄ“Å”anas laikā.

Kā darbojas relāciju datu bāzes (1. daļa)

Kā redzat, Å”eit ir vairāk mezglu (divas reizes). PatieŔām, jums ir papildu mezgli, "lēmuma mezgli", kas palÄ«dzēs atrast pareizo mezglu (kas saglabā saistÄ«tās tabulas rindu atraÅ”anās vietu). Bet meklÄ“Å”anas sarežģītÄ«ba joprojām ir O(log(N)) (ir tikai vēl viens lÄ«menis). Lielā atŔķirÄ«ba ir tā mezgli zemākajā lÄ«menÄ« ir saistÄ«ti ar to pēctečiem.

Izmantojot Å”o B+Tree, ja meklējat vērtÄ«bas no 40 lÄ«dz 100:

  • Jums vienkārÅ”i jāmeklē 40 (vai tuvākā vērtÄ«ba pēc 40, ja 40 neeksistē), kā to darÄ«jāt ar iepriekŔējo koku.
  • Pēc tam savāc 40 mantiniekus, izmantojot tieŔās mantinieku saites, lÄ«dz sasniegsiet 100.

Pieņemsim, ka atrodat M pēctečus un kokam ir N mezgli. Konkrēta mezgla atraÅ”ana maksā žurnālu(N), tāpat kā iepriekŔējais koks. Bet, tiklÄ«dz jÅ«s iegÅ«sit Å”o mezglu, jÅ«s iegÅ«sit M operāciju pēcteci ar atsaucēm uz viņu pēctečiem. Å Ä« meklÄ“Å”ana maksā tikai M+log(N) operācijas, salÄ«dzinot ar N operācijām iepriekŔējā kokā. Turklāt jums nav jālasa viss koks (tikai M+log(N) mezgli), kas nozÄ«mē mazāku diska lietojumu. Ja M ir mazs (piem., 200 rindas) un N ir liels (1 000 000 rindu), bÅ«s LIELA atŔķirÄ«ba.

Bet Å”eit ir jaunas problēmas (atkal!). Ja pievienojat vai dzÄ“Å”at rindu datu bāzē (un lÄ«dz ar to saistÄ«tajā B+Tree indeksā):

  • jums ir jāuztur kārtÄ«ba starp mezgliem B+Tree iekÅ”pusē, pretējā gadÄ«jumā jÅ«s nevarēsit atrast mezglus neŔķirota koka iekÅ”pusē.
  • jums ir jāsaglabā minimālais iespējamais lÄ«meņu skaits B+Tree, pretējā gadÄ«jumā O(log(N)) laika sarežģītÄ«ba kļūst par O(N).

Citiem vārdiem sakot, B+Tree ir jābÅ«t paÅ”sakārtotam un lÄ«dzsvarotam. Par laimi, tas ir iespējams, izmantojot viedās dzÄ“Å”anas un ievietoÅ”anas darbÄ«bas. Bet par to ir jāmaksā: ievietoÅ”ana un dzÄ“Å”ana B+ kokā maksā O(log(N)). Tāpēc daži no jums to ir dzirdējuÅ”i Pārāk daudzu indeksu izmantoÅ”ana nav laba ideja. TieŔām, jÅ«s palēnināt ātru rindas ievietoÅ”anu/atjaunināŔanu/dzÄ“Å”anu tabulājo datu bāzei ir jāatjaunina tabulas indeksi, izmantojot dārgu O(log(N)) operāciju katram indeksam. Turklāt indeksu pievienoÅ”ana nozÄ«mē lielāku darba slodzi darÄ«jumu vadÄ«tājs (tiks aprakstÄ«ts raksta beigās).

Lai iegÅ«tu sÄ«kāku informāciju, varat skatÄ«t Wikipedia rakstu par B+Koks. Ja vēlaties piemēru B+Tree ievieÅ”anai datu bāzē, ieskatieties Å”is raksts Šø Å”is raksts no vadoŔā MySQL izstrādātāja. Viņi abi koncentrējas uz to, kā InnoDB (MySQL dzinējs) apstrādā indeksus.

Piezīme. Kāds lasītājs man teica, ka zema līmeņa optimizācijas dēļ kokam B+ jābūt pilnībā līdzsvarotam.

Hashtable

MÅ«su pēdējā svarÄ«gā datu struktÅ«ra ir hash tabula. Tas ir ļoti noderÄ«gi, ja vēlaties ātri meklēt vērtÄ«bas. Turklāt, izprotot jaukÅ”anas tabulu, mēs vēlāk varēsim izprast parasto datu bāzes pievienoÅ”anas darbÄ«bu, ko sauc par jaukÅ”anas pievienoÅ”anu ( hash pievienoties). Å o datu struktÅ«ru datu bāze izmanto arÄ« dažu iekŔējo lietu glabāŔanai (piem. slēdzams galds vai bufera baseins, mēs abus Å”os jēdzienus redzēsim vēlāk).

Hash tabula ir datu struktūra, kas ātri atrod elementu pēc atslēgas. Lai izveidotu hash tabulu, jums jādefinē:

  • pavediens jÅ«su elementiem
  • jaucējfunkcija par atslēgām. Aprēķinātās atslēgas jaucējzÄ«mes norāda elementu atraÅ”anās vietu (ko sauc segmentiem ).
  • funkciju taustiņu salÄ«dzināŔanai. Kad esat atradis pareizo segmentu, jums ir jāatrod elements, kuru meklējat segmentā, izmantojot Å”o salÄ«dzinājumu.

VienkārÅ”s piemērs

Ņemsim skaidru piemēru:

Kā darbojas relāciju datu bāzes (1. daļa)

Å ajā hash tabulā ir 10 segmenti. Tā kā es esmu slinks, es nobildēju tikai 5 segmentus, bet es zinu, ka tu esi gudrs, tāpēc ļauÅ”u tev paÅ”am iztēloties pārējos 5. Es izmantoju atslēgas jaucējfunkciju modulo 10. Citiem vārdiem sakot, es saglabāju tikai elementa atslēgas pēdējo ciparu, lai atrastu tā segmentu:

  • ja pēdējais cipars ir 0, elements ietilpst segmentā 0,
  • ja pēdējais cipars ir 1, elements ietilpst segmentā 1,
  • ja pēdējais cipars ir 2, elements ietilpst apgabalā 2,
  • ...

SalīdzināŔanas funkcija, ko izmantoju, ir vienkārŔi vienādība starp diviem veseliem skaitļiem.

Pieņemsim, ka vēlaties iegÅ«t 78. elementu:

  • Hash tabula aprēķina jaucējkodu 78, kas ir 8.
  • Jauktabula aplÅ«ko 8. segmentu, un pirmais atrastais elements ir 78.
  • Viņa atdod jums 78. preci
  • MeklÄ“Å”ana maksā tikai 2 operācijas (viens, lai aprēķinātu jaucējvērtÄ«bu, un otrs, lai meklētu elementu segmentā).

Tagad pieņemsim, ka vēlaties iegÅ«t 59. elementu:

  • Hash tabula aprēķina jaucējkodu 59, kas ir 9.
  • Hash tabula meklē segmentā 9, pirmais atrastais elements ir 99. Tā kā 99!=59, elements 99 nav derÄ«gs elements.
  • Izmantojot to paÅ”u loÄ£iku, tiek ņemts otrais elements (9), treÅ”ais (79), ..., pēdējais (29).
  • Elements nav atrasts.
  • MeklÄ“Å”ana izmaksāja 7 operācijas.

Laba hash funkcija

Kā redzat, atkarībā no meklētās vērtības izmaksas nav vienādas!

Ja tagad mainÄ«Å”u atslēgas jaucējfunkciju modulo 1 000 000 (tas ir, ņemot pēdējos 6 ciparus), otrā uzmeklÄ“Å”ana maksā tikai 1 operāciju, jo segmentā 000059 nav elementu. Patiesais izaicinājums ir atrast labu jaucējfunkciju, kas izveidos kausus, kas satur ļoti mazu elementu skaitu.

Manā piemērā ir viegli atrast labu jaucējfunkciju. Bet Å”is ir vienkārÅ”s piemērs, labu jaucējfunkciju atrast ir grÅ«tāk, ja atslēga ir:

  • virkne (piemēram, uzvārds)
  • 2 rindas (piemēram, uzvārds un vārds)
  • 2 rindas un datums (piemēram, uzvārds, vārds un dzimÅ”anas datums)
  • ...

Izmantojot labu jaucējfunkciju, jaucēj tabulas meklÄ“Å”ana maksā O (1).

Tabula Masīvs vs hash

Kāpēc neizmantot masīvu?

Hmm, labs jautājums.

  • Hash tabula var bÅ«t daļēji ielādēts atmiņā, un atlikuÅ”ie segmenti var palikt diskā.
  • Izmantojot masÄ«vu, atmiņā ir jāizmanto blakus esoŔā vieta. Ja ielādējat lielu galdu ir ļoti grÅ«ti atrast pietiekami daudz nepārtrauktas vietas.
  • JaukÅ”anas tabulai varat atlasÄ«t vajadzÄ«go atslēgu (piemēram, valsti un personas uzvārdu).

Lai iegÅ«tu papildinformāciju, varat izlasÄ«t rakstu par JavaHashMap, kas ir efektÄ«va hash tabulas ievieÅ”ana; jums nav jāsaprot Java, lai saprastu Å”ajā rakstā aplÅ«kotos jēdzienus.

Avots: www.habr.com

Pievieno komentāru