Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā

Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā

ievads

Es sniedzu Å”o ziņojumu angļu valodā GopherCon Russia 2019 konferencē Maskavā un krievu valodā sanāksmē Ņižņijnovgorodā. Mēs runājam par bitkartes indeksu - retāk nekā B-koks, bet ne mazāk interesants. DalÄ«Å”anās ieraksts uzstāŔanās konferencē angļu valodā un teksta atÅ”ifrējumi krievu valodā.

ApskatÄ«sim, kā darbojas bitkartes indekss, kad tas ir labāks, kad sliktāks par citiem indeksiem un kādos gadÄ«jumos tas ir ievērojami ātrāks par tiem; ApskatÄ«sim, kurām populārajām DBVS jau ir bitkartes indeksi; Mēģināsim uzrakstÄ«t savu Go. Un ā€œdesertāā€ mēs izmantosim gatavas bibliotēkas, lai izveidotu savu Ä«paÅ”i ātru specializēto datu bāzi.

Ļoti ceru, ka mani darbi jums būs noderīgi un interesanti. Aiziet!

Ievads


http://bit.ly/bitmapindexes
https://github.com/mkevac/gopherconrussia2019

Sveiki visiem! Ir seÅ”i vakarā, un mēs visi esam ļoti noguruÅ”i. Lielisks laiks runāt par garlaicÄ«go datu bāzes indeksu teoriju, vai ne? Neuztraucieties, man Å”eit un tur bÅ«s dažas avota koda rindiņas. šŸ™‚

Visus jokus malā, ziņojums ir pilns ar informāciju, un mums nav daudz laika. Tātad sāksim.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Šodien es runāŔu par Ŕādiem jautājumiem:

  • kas ir indeksi;
  • kas ir bitkartes indekss;
  • kur tas tiek izmantots un kur NETIEK lietots un kāpēc;
  • vienkārÅ”a ievieÅ”ana Go un neliela cīņa ar kompilatoru;
  • nedaudz mazāk vienkārÅ”a, bet daudz produktÄ«vāka ievieÅ”ana Go montētājā;
  • bitkartes indeksu ā€œproblēmasā€;
  • esoŔās implementācijas.

Tātad, kas ir indeksi?

Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā

Indekss ir atseviŔķa datu struktÅ«ra, kuru mēs uzturam un atjauninām papildus galvenajiem datiem. To izmanto, lai paātrinātu meklÄ“Å”anu. Ja nebÅ«tu indeksu, meklÄ“Å”anai bÅ«tu nepiecieÅ”ams pilnÄ«bā izpētÄ«t datus (process, ko sauc par pilnu skenÄ“Å”anu), un Å”im procesam ir lineāra algoritmiskā sarežģītÄ«ba. Taču datubāzēs parasti ir milzÄ«gs datu apjoms, un lineārā sarežģītÄ«ba ir pārāk lēna. Ideālā gadÄ«jumā mēs iegÅ«tu logaritmisku vai konstantu.

Å Ä« ir ļoti sarežģīta tēma, kas ir piepildÄ«ta ar smalkumiem un kompromisiem, taču, aplÅ«kojot gadu desmitiem ilguÅ”u datubāzes izstrādi un pētniecÄ«bu, esmu gatavs teikt, ka ir tikai dažas plaÅ”i izmantotas pieejas datu bāzes indeksu izveidei.

Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā

Pirmā pieeja ir meklÄ“Å”anas telpas hierarhiska samazināŔana, sadalot meklÄ“Å”anas telpu mazākās daļās.

Mēs parasti to darām, izmantojot dažāda veida kokus. Piemērs varētu bÅ«t liela materiālu kaste jÅ«su skapÄ«, kurā ir mazākas materiālu kastes, kas sadalÄ«tas pa dažādām tēmām. Ja jums ir nepiecieÅ”ami materiāli, jÅ«s, iespējams, meklēsit tos lodziņā, kurā ir rakstÄ«ts "Materiāli", nevis tajā, kas rakstÄ«ts "SÄ«kfaili", vai ne?

Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā

Otra pieeja ir nekavējoties atlasÄ«t vajadzÄ«go elementu vai elementu grupu. Mēs to darām hash kartēs vai reversajos indeksos. Jaucējkartes izmantoÅ”ana ir ļoti lÄ«dzÄ«ga iepriekŔējam piemēram, taču kastÄ«Å”u vietā jÅ«su skapÄ« ir Ä·ekars mazu kastÄ«Å”u ar galÄ«gajiem priekÅ”metiem.

Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā

TreŔā pieeja ir novērst nepiecieÅ”amÄ«bu meklēt. Mēs to darām, izmantojot Bloom filtrus vai dzeguzes filtrus. Pirmie sniedz atbildi uzreiz, pasargājot jÅ«s no nepiecieÅ”amÄ«bas meklēt.

Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā

Pēdējā pieeja ir pilnÄ«bā izmantot visu jaudu, ko mums sniedz mÅ«sdienu aparatÅ«ra. Tas ir tieÅ”i tas, ko mēs darām bitkartes indeksos. Jā, tos lietojot, mums dažreiz ir jāiziet viss rādÄ«tājs, taču mēs to darām ļoti efektÄ«vi.

Kā jau teicu, datu bāzes indeksu tēma ir plaÅ”a un kompromisu pilna. Tas nozÄ«mē, ka dažreiz mēs varam izmantot vairākas pieejas vienlaikus: ja mums vēl vairāk jāpaātrina meklÄ“Å”ana vai ja jāaptver visi iespējamie meklÄ“Å”anas veidi.

Šodien es runāŔu par vismazāk zināmo pieeju no tiem - bitkartes indeksiem.

Kas es esmu, lai runātu par Å”o tēmu?

Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā

Es strādāju kā Badoo komandas vadītājs (iespējams, jūs esat vairāk pazīstams ar citu mūsu produktu Bumble). Mums jau ir vairāk nekā 400 miljoni lietotāju visā pasaulē un daudzas funkcijas, kas izvēlas viņiem piemērotāko. Mēs to darām, izmantojot pielāgotus pakalpojumus, tostarp bitkartes indeksus.

Tātad, kas ir bitkartes indekss?

Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Bitkartes indeksi, kā norāda nosaukums, izmanto bitkartes vai bitkopas, lai ieviestu meklÄ“Å”anas indeksu. Skatoties no putna lidojuma, Å”is indekss sastāv no vienas vai vairākām Ŕādām bitkartēm, kas attēlo jebkuru entÄ«tiju (piemēram, cilvēkus) un to Ä«paŔības vai parametrus (vecumu, acu krāsu utt.), un algoritmu, kas izmanto bitu darbÄ«bas (UN, OR, NOT). ), lai atbildētu uz meklÄ“Å”anas vaicājumu.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Mums ir teikts, ka bitkartes indeksi ir vispiemērotākie un ļoti efektÄ«vi gadÄ«jumiem, kad tiek veikti meklējumi, kuros tiek apvienoti vaicājumi daudzās zemas kardinalitātes kolonnās (domājiet par "acu krāsu" vai "Ä£imenes stāvokli" salÄ«dzinājumā ar "attālumu no pilsētas centra"). Bet es parādÄ«Å”u vēlāk, ka tie lieliski darbojas arÄ« augstas kardinalitātes kolonnām.

ApskatÄ«sim vienkārŔāko bitkartes indeksa piemēru.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Iedomājieties, ka mums ir saraksts ar Maskavas restorāniem ar tādām binārajām īpaŔībām kā:

  • netālu no metro;
  • ir privāta autostāvvieta;
  • ir veranda (ir terase);
  • var rezervēt galdiņu (pieņem rezervācijas);
  • piemērots veÄ£etārieÅ”iem (draudzÄ«gs vegāniem);
  • dārgi (dārgi).

Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
PieŔķirsim katram restorānam kārtas numuru, sākot no 0, un atvēlēsim atmiņu 6 bitkartēm (vienu katram raksturlielumam). Pēc tam mēs aizpildÄ«sim Ŕīs bitkartes atkarÄ«bā no tā, vai restorānam ir Å”is Ä«paÅ”ums vai nav. Ja 4. restorānam ir veranda, bitkartē ā€œir verandaā€ bits Nr. 4 tiks iestatÄ«ts uz 1 (ja nav verandas, tad uz 0).
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Tagad mums ir vienkārŔākais iespējamais bitkartes indekss, un mēs varam to izmantot, lai atbildētu uz tādiem vaicājumiem kā:

  • ā€œRādÄ«t man veÄ£etārieÅ”iem draudzÄ«gus restorānusā€;
  • "Parādiet man lētus restorānus ar verandu, kur varat rezervēt galdiņu."

Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Kā? PaskatÄ«simies. Pirmais pieprasÄ«jums ir ļoti vienkārÅ”s. Viss, kas mums jādara, ir ņemt ā€œveÄ£etārieÅ”iem draudzÄ«goā€ bitkarti un pārvērst to par restorānu sarakstu, kuru fragmenti ir atklāti.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Otrais pieprasÄ«jums ir nedaudz sarežģītāks. Mums ir jāizmanto bitkarte NOT ā€œdārgajāā€ bitkartē, lai iegÅ«tu lētu restorānu sarakstu, pēc tam UN tā ar bitkarti ā€œvai es varu rezervēt galdiņuā€ un UN rezultāts ar bitkarti ā€œir verandaā€. IegÅ«tajā bitkartē bÅ«s saraksts ar iestādēm, kas atbilst visiem mÅ«su kritērijiem. Å ajā piemērā tas ir tikai Yunost restorāns.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Ir daudz teoriju, taču neuztraucieties, mēs redzēsim kodu ļoti drīz.

Kur tiek izmantoti bitkartes indeksi?

Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Ja jūs Google bitmap indeksus, 90% atbilžu būs saistīti ar Oracle DB vienā vai otrā veidā. Bet droŔi vien arī citas DBVS atbalsta tik forŔu lietu, vai ne? Ne īsti.

Izskatīsim galveno aizdomās turamo sarakstu.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
MySQL vēl neatbalsta bitkartes indeksus, taču ir priekÅ”likums, kas iesaka pievienot Å”o opciju (https://dev.mysql.com/worklog/task/?id=1524).

PostgreSQL neatbalsta bitkartes indeksus, bet izmanto vienkārÅ”as bitkartes un bitu darbÄ«bas, lai apvienotu meklÄ“Å”anas rezultātus vairākos citos indeksos.

Tarantool ir bitkopu indeksi un atbalsta vienkārÅ”u meklÄ“Å”anu tajos.

Redis ir vienkārÅ”i bitlauki (https://redis.io/commands/bitfield) bez iespējas tos meklēt.

MongoDB vēl neatbalsta bitkartes indeksus, taču ir arÄ« priekÅ”likums, kas iesaka pievienot Å”o opciju https://jira.mongodb.org/browse/SERVER-1723

Elasticsearch iekŔēji izmanto bitkartes (https://www.elastic.co/blog/frame-of-reference-and-roaring-bitmaps).

Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā

  • Bet mÅ«su mājā ir parādÄ«jies jauns kaimiņŔ: Pilosa. Å Ä« ir jauna nerelāciju datubāze, kas rakstÄ«ta Go. Tajā ir tikai bitkartes indeksi un viss tiek balstÄ«ts uz tiem. Mēs par to runāsim nedaudz vēlāk.

IevieŔana Go

Bet kāpēc bitkartes indeksi tiek izmantoti tik reti? Pirms atbildēt uz Å”o jautājumu, es vēlos jums parādÄ«t, kā programmā Go ieviest ļoti vienkārÅ”u bitkartes indeksu.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Bitkartes bÅ«tÄ«bā ir tikai datu gabali. Programmā Go Å”im nolÅ«kam izmantosim baitu Ŕķēles.

Mums ir viena bitkarte vienam restorāna raksturlielumam, un katrs bitkartes bits norāda, vai konkrētam restorānam ir Ŕī Ä«paŔība vai nav.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Mums bÅ«s nepiecieÅ”amas divas palÄ«gfunkcijas. Viens tiks izmantots, lai aizpildÄ«tu mÅ«su bitkartes ar nejauÅ”iem datiem. NejauÅ”i, bet ar zināmu varbÅ«tÄ«bu, ka restorānā ir katrs Ä«paÅ”ums. Piemēram, es uzskatu, ka Maskavā ir ļoti maz restorānu, kur nevar rezervēt galdiņu, un man Ŕķiet, ka aptuveni 20% iestāžu ir piemērotas veÄ£etārieÅ”iem.

Otrā funkcija pārveidos bitkarti restorānu sarakstā.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Lai atbildētu uz vaicājumu ā€œRādÄ«t man lētus restorānus, kuriem ir terase un kuros var veikt rezervācijasā€, mums ir nepiecieÅ”amas divu bitu darbÄ«bas: NOT un UN.

Mēs varam nedaudz vienkārÅ”ot savu kodu, izmantojot sarežģītāku operatoru AND NOT.

Mums ir funkcijas katrai no Ŕīm operācijām. Abi iziet cauri Ŕķēlēm, paņem no katra atbilstoÅ”os elementus, apvieno tos ar bitu darbÄ«bu un ieliek iegÅ«tajā Ŕķēlē rezultātu.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Un tagad mēs varam izmantot mÅ«su bitkartes un funkcijas, lai atbildētu uz meklÄ“Å”anas vaicājumu.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Veiktspēja nav tik augsta, lai gan funkcijas ir ļoti vienkārÅ”as un mēs ietaupÄ«jām daudz naudas, neatgriežot jaunu iegÅ«to daļu katru reizi, kad funkcija tika izsaukta.

Pēc nelielas profilÄ“Å”anas ar pprof es pamanÄ«ju, ka Go kompilatoram trÅ«kst vienas ļoti vienkārÅ”as, bet ļoti svarÄ«gas optimizācijas: funkciju iekļauÅ”ana.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Fakts ir tāds, ka Go kompilators Å”ausmÄ«gi baidās no cilpām, kas iet cauri Ŕķēlumiem, un kategoriski atsakās iekļaut funkcijas, kas satur Ŕādas cilpas.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Bet es nebaidos un varu apmānīt kompilatoru, cilpas vietā izmantojot goto, kā vecajos labajos laikos.

Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā

Un, kā redzat, tagad kompilators ar prieku iekļaus mūsu funkciju! Rezultātā mums izdodas ietaupīt aptuveni 2 mikrosekundes. Nav slikti!

Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā

Otro vājo vietu ir viegli pamanÄ«t, rÅ«pÄ«gi aplÅ«kojot montāžas izvadi. Kompilators pievienoja Ŕķēluma robežu pārbaudi tieÅ”i mÅ«su karstākajā cilpā. Fakts ir tāds, ka Go ir droÅ”a valoda, kompilators baidās, ka mani trÄ«s argumenti (trÄ«s Ŕķēles) ir dažāda izmēra. Galu galā tad teorētiski pastāvēs tā sauktā bufera pārpildes iespējamÄ«ba.

Pārliecināsim kompilatoru, parādot, ka visas Ŕķēles ir vienāda izmēra. Mēs to varam izdarÄ«t, funkcijas sākumā pievienojot vienkārÅ”u pārbaudi.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
To redzot, kompilators laimīgi izlaiž pārbaudi, un mēs galu galā ietaupām vēl 500 nanosekundes.

Lieli buči

Labi, mums izdevās izspiest veiktspēju no mÅ«su vienkārŔās ievieÅ”anas, taču Å”is rezultāts patiesÄ«bā ir daudz sliktāks, nekā tas ir iespējams ar paÅ”reizējo aparatÅ«ru.

Mēs darām tikai pamata bitu darbÄ«bas, un mÅ«su procesori tās veic ļoti efektÄ«vi. Bet diemžēl mēs savu procesoru ā€œbarojamā€ ar ļoti maziem darbiem. MÅ«su funkcijas veic darbÄ«bas pa baitiem. Mēs varam ļoti viegli pielāgot savu kodu, lai tas darbotos ar 8 baitu gabaliem, izmantojot UInt64 Ŕķēles.

Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā

Kā redzat, Ŕīs nelielās izmaiņas paātrināja mÅ«su programmu astoņas reizes, palielinot partijas lielumu astoņas reizes. Var teikt, ka ieguvums ir lineārs.

Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā

IevieÅ”ana montētājā

Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Bet tas nav beigas. MÅ«su procesori var strādāt ar 16, 32 un pat 64 baitu gabaliem. Šādas ā€œplaÅ”asā€ operācijas sauc par vienas instrukcijas vairākiem datiem (SIMD; viena instrukcija, daudzi dati), un koda pārveidoÅ”anas procesu, lai tas izmantotu Ŕādas darbÄ«bas, sauc par vektorizāciju.

Diemžēl Go kompilators ne tuvu nav izcils vektorizācijā. PaÅ”laik vienÄ«gais veids, kā vektorizēt Go kodu, ir veikt Ŕīs darbÄ«bas manuāli, izmantojot Go montētāju.

Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā

Go montētājs ir dÄ«vains zvērs. JÅ«s droÅ”i vien zināt, ka montāžas valoda ir ļoti saistÄ«ta ar tā datora arhitektÅ«ru, kuram rakstāt, taču tas tā nav Go gadÄ«jumā. Go assembler ir vairāk kā IRL (starpposma reprezentācijas valoda) vai starpvaloda: tā ir praktiski neatkarÄ«ga no platformas. Robs Paiks sniedza lielisku sniegumu Ziņot par Å”o tēmu pirms vairākiem gadiem GopherCon Denverā.

Turklāt Go izmanto neparastu Plan 9 formātu, kas atŔķiras no vispārpieņemtajiem AT&T un Intel formātiem.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Var droŔi teikt, ka rakstīt Go assembler ar roku nav tas jautrākais.

Bet, par laimi, jau ir divi augsta līmeņa rīki, kas palīdz mums uzrakstīt Go assembler: PeachPy un avo. Abas utilītas ģenerē Go montētāju no augstāka līmeņa koda, kas rakstīts attiecīgi Python un Go.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Å Ä«s utilÄ«tas vienkārÅ”o tādas lietas kā reÄ£istru pieŔķirÅ”ana, rakstÄ«Å”anas cilpas un kopumā vienkārÅ”o procesu, kā iekļūt montāžas programmÄ“Å”anas pasaulē Go.

Mēs izmantosim avo, tāpēc mūsu programmas būs gandrīz parastas Go programmas.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Šādi izskatās vienkārŔākais avo programmas piemērs. Mums ir funkcija main(), kas sevÄ« definē Add() funkciju, kuras nozÄ«me ir divu skaitļu pievienoÅ”ana. Å eit ir palÄ«gfunkcijas, lai iegÅ«tu parametrus pēc nosaukuma un iegÅ«tu kādu no bezmaksas un piemērotiem procesoru reÄ£istriem. Katrai procesora darbÄ«bai ir atbilstoÅ”a funkcija avo, kā redzams ADDQ. Visbeidzot, mēs redzam palÄ«gfunkciju iegÅ«tās vērtÄ«bas saglabāŔanai.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Izsaucot go generate, mēs izpildīsim programmu avo un rezultātā tiks ģenerēti divi faili:

  • add.s ar iegÅ«to kodu Go montētājā;
  • stub.go ar funkciju galvenēm, lai savienotu divas pasaules: Go un assembler.

Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Tagad, kad esam redzējuÅ”i, ko un kā dara avo, apskatÄ«sim mÅ«su funkcijas. Es ieviesu gan skalārās, gan vektora (SIMD) funkciju versijas.

Vispirms apskatīsim skalārās versijas.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Tāpat kā iepriekŔējā piemērā, mēs pieprasām bezmaksas un derÄ«gu vispārējas nozÄ«mes reÄ£istru, mums nav jāaprēķina argumentu nobÄ«des un izmēri. avo to visu dara mÅ«su vietā.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Mēs izmantojām etiÄ·etes un goto (vai lēcienus), lai uzlabotu veiktspēju un pieviltu Go kompilatoru, bet tagad mēs to darām no paÅ”a sākuma. Lieta tāda, ka cikli ir augstāka lÄ«meņa jēdziens. Montētājā mums ir tikai etiÄ·etes un lēcieni.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
AtlikuÅ”ajam kodam jau vajadzētu bÅ«t pazÄ«stamam un saprotamam. Mēs emulējam cilpu ar etiÄ·etēm un lēcieniem, paņemam nelielu datu fragmentu no mÅ«su divām daļām, apvienojam tos ar bitu darbÄ«bu (UN Å”ajā gadÄ«jumā NE) un pēc tam ievietojam rezultātu iegÅ«tajā daļā. Visi.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Šādi izskatās galīgais montētāja kods. Mums nebija jāaprēķina nobīdes un izmēri (izcelti zaļā krāsā) vai jāseko līdzi izmantotajiem reģistriem (izcelti sarkanā krāsā).
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Ja salÄ«dzinām montāžas valodas ievieÅ”anas veiktspēju ar Go labākās ievieÅ”anas veiktspēju, mēs redzēsim, ka tā ir tāda pati. Un tas ir gaidāms. Galu galā mēs neko Ä«paÅ”u nedarÄ«jām - mēs vienkārÅ”i reproducējām to, ko darÄ«tu Go kompilators.

Diemžēl mēs nevaram piespiest kompilatoru iekļaut mÅ«su funkcijas, kas rakstÄ«tas montāžas valodā. Go kompilatoram Å”obrÄ«d Ŕādas iespējas nav, lai gan jau labu laiku ir bijis lÅ«gums to pievienot.

Tāpēc montāžas valodā no mazām funkcijām nav iespējams gūt nekādu labumu. Mums ir vai nu jāraksta lielas funkcijas, vai jāizmanto jaunā matemātikas/bitu pakotne, vai arī jāapiet montētāja valoda.

Tagad apskatīsim mūsu funkciju vektorversijas.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Å ajā piemērā es nolēmu izmantot AVX2, tāpēc mēs izmantosim darbÄ«bas, kas darbojas ar 32 baitu gabaliem. Koda struktÅ«ra ir ļoti lÄ«dzÄ«ga skalārajai versijai: tiek ielādēti parametri, tiek pieprasÄ«ts bezmaksas kopÄ«gs reÄ£istrs utt.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Viens no jauninājumiem ir tas, ka plaŔākās vektoru operācijās tiek izmantoti Ä«paÅ”i plaÅ”i reÄ£istri. 32 baitu gabalos tie ir reÄ£istri ar prefiksu Y. Tāpēc kodā ir redzama funkcija YMM(). Ja es izmantotu AVX-512 ar 64 bitu gabaliem, prefikss bÅ«tu Z.

Otrs jauninājums ir tāds, ka es nolēmu izmantot optimizāciju, ko sauc par cilpas atritināŔanu, kas nozÄ«mē manuāli veikt astoņas cilpas darbÄ«bas, pirms pāriet uz cilpas sākumu. Å Ä« optimizācija samazina koda filiāļu skaitu, un to ierobežo pieejamo bezmaksas reÄ£istru skaits.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Nu, kā ar sniegumu? Viņa ir skaista! Salīdzinājumā ar labāko Go risinājumu mēs panācām aptuveni septiņas reizes lielāku ātrumu. Iespaidīgi, vai ne?
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Taču pat Å”o ievieÅ”anu var potenciāli paātrināt, vaicājumu plānotājam izmantojot AVX-512, priekÅ”ielādÄ“Å”anu vai JIT (just-in-time kompilatoru). Bet Ŕī noteikti ir atseviŔķa ziņojuma tēma.

Problēmas ar bitkartes indeksiem

Tagad, kad esam jau apskatÄ«juÅ”i vienkārÅ”u bitkartes indeksa ievieÅ”anu Go un daudz produktÄ«vāku montāžas valodā, beidzot parunāsim par to, kāpēc bitkartes indeksi tiek izmantoti tik reti.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Vecāki raksti piemin trÄ«s problēmas ar bitkartes indeksiem, bet jaunākos rakstos es apgalvoju, ka tie vairs nav aktuāli. Mēs neiedziļināsimies katrā no Ŕīm problēmām, bet aplÅ«kosim tās virspusēji.

Augstas kardinalitātes problēma

Tātad mums ir teikts, ka bitkartes indeksi ir piemēroti tikai laukiem ar zemu kardinalitāti, tas ir, tiem, kuriem ir maz vērtÄ«bu (piemēram, dzimums vai acu krāsa), un iemesls ir tāds, ka parastie Ŕādu lauku attēlojumi (viens bit per value) augstas kardinalitātes gadÄ«jumā tas aizņems pārāk daudz vietas un turklāt Å”ie bitkartes indeksi tiks slikti (reti) aizpildÄ«ti.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Dažreiz mēs varam izmantot citu attēlojumu, piemēram, standarta, ko izmantojam skaitļu attēloÅ”anai. Bet tas bija saspieÅ”anas algoritmu parādÄ«Å”anās, kas mainÄ«ja visu. Pēdējo desmitgažu laikā zinātnieki un pētnieki ir izstrādājuÅ”i lielu skaitu bitkartes saspieÅ”anas algoritmu. To galvenā priekÅ”rocÄ«ba ir tāda, ka nav nepiecieÅ”ams atspiest bitkartes, lai veiktu bitu operācijas ā€“ mēs varam veikt bitu operācijas tieÅ”i uz saspiestām bitkartēm.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Pēdējā laikā ir sākuÅ”as parādÄ«ties hibrÄ«dās pieejas, piemēram, rÅ«coÅ”as bitkartes. Tie vienlaikus izmanto trÄ«s dažādus bitkartes attēlojumus ā€“ paÅ”us bitkartes, masÄ«vus un tā sauktos bitu palaiÅ”anas veidus ā€“ un lÄ«dzsvaro starp tiem, lai palielinātu veiktspēju un samazinātu atmiņas patēriņu.

Populārākajās lietojumprogrammās varat atrast rÅ«coÅ”as bitkartes. Jau tagad ir milzÄ«gs skaits ievieÅ”anu visdažādākajām programmÄ“Å”anas valodām, tostarp vairāk nekā trÄ«s ievieÅ”anas Go.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Vēl viena pieeja, kas var mums palÄ«dzēt tikt galā ar augstu kardinalitāti, tiek saukta par binning. Iedomājieties, ka jums ir lauks, kas attēlo cilvēka augumu. Augstums ir peldoŔā komata skaitlis, bet mēs, cilvēki, par to tā nedomājam. Mums nav atŔķirÄ«bas starp augumu 185,2 cm un 185,3 cm.

Izrādās, ka līdzīgas vērtības varam sagrupēt grupās 1 cm robežās.

Un, ja mēs zinām arī to, ka ļoti maz cilvēku ir garāki par 50 cm un garāki par 250 cm, tad mēs būtībā varam pārvērst lauku ar bezgalīgu kardinalitāti par lauku, kura kardinalitāte ir aptuveni 200 vērtības.

Protams, ja nepiecieÅ”ams, pēc tam varam veikt papildus filtrÄ“Å”anu.

Liela joslas platuma problēma

Nākamā problēma ar bitkartes indeksiem ir tāda, ka to atjaunināŔana var bÅ«t ļoti dārga.

Datu bāzēm ir jāspēj atjaunināt datus, kamēr, iespējams, simtiem citu vaicājumu meklē datus. Mums ir nepiecieÅ”amas slēdzenes, lai izvairÄ«tos no problēmām ar vienlaicÄ«gu piekļuvi datiem vai citām koplietoÅ”anas problēmām. Un kur ir viena liela slēdzene, tur ir problēma - slēdzenes strÄ«ds, kad Ŕī slēdzene kļūst par pudeli.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Å o problēmu var atrisināt vai apiet, izmantojot sadalÄ«Å”anu vai versiju indeksus.

DalÄ«Å”ana ir vienkārÅ”a un labi zināma lieta. Varat sadalÄ«t bitkartes indeksu tāpat kā jebkurus citus datus. Vienas lielas slēdzenes vietā jÅ«s iegÅ«sit virkni mazu slēdzeņu un tādējādi atbrÄ«vosities no strÄ«diem par slēdzenēm.

Otrs veids, kā atrisināt problēmu, ir izmantot versiju indeksus. Jums var bÅ«t viena indeksa kopija, ko izmantojat meklÄ“Å”anai vai lasÄ«Å”anai, un viena, ko izmantojat rakstÄ«Å”anai vai atjaunināŔanai. Un vienreiz noteiktā laika periodā (piemēram, reizi 100 ms vai 500 ms) jÅ«s tos dublējat un apmainiet. Protams, Ŕī pieeja ir piemērojama tikai gadÄ«jumos, kad jÅ«su lietojumprogramma var apstrādāt nedaudz atpaliekoÅ”u meklÄ“Å”anas indeksu.

Šīs divas pieejas var izmantot vienlaikus: jums var būt sadalīts versiju indekss.

Sarežģītāki vaicājumi

Pēdējā problēma ar bitkartes indeksiem ir tāda, ka mums tiek teikts, ka tie nav labi piemēroti sarežģītākiem vaicājumu veidiem, piemēram, span vaicājumiem.

PatieŔām, ja tā padomā, bitu darbÄ«bas, piemēram, UN, VAI utt., nav Ä«paÅ”i piemērotas vaicājumiem a la ā€œParādÄ«t man viesnÄ«cas ar numuru cenām no 200 lÄ«dz 300 dolāriem par naktiā€.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Naivs un ļoti neprātīgs risinājums būtu ņemt rezultātus katrai dolāra vērtībai un apvienot tos ar bitwise VAI darbību.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Nedaudz labāks risinājums bÅ«tu izmantot grupÄ“Å”anu. Piemēram, grupās pa 50 dolāriem. Tas paātrinātu mÅ«su procesu 50 reizes.

Taču problēma ir arÄ« viegli atrisināma, izmantojot skatu, kas izveidots Ä«paÅ”i Ŕāda veida pieprasÄ«jumam. Zinātniskajos rakstos to sauc par diapazonā kodētām bitkartēm.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Å ajā attēlojumā mēs ne tikai iestatām vienu bitu kādai vērtÄ«bai (piemēram, 200), bet iestatām Å”o vērtÄ«bu un visu augstāku. 200 un vairāk. Tas pats 300: 300 un vairāk. Un tā tālāk.

Izmantojot Å”o attēlojumu, mēs varam atbildēt uz Ŕāda veida meklÄ“Å”anas vaicājumu, Ŕķērsojot indeksu tikai divas reizes. Vispirms mēs iegÅ«sim sarakstu ar viesnÄ«cām, kurās numuriņŔ maksā mazāk vai 300 USD, un pēc tam no tā izņemsim tās, kurās numuriņa izmaksas ir mazākas vai USD 199. Gatavs.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
JÅ«s bÅ«siet pārsteigts, bet pat Ä£eovaicājumi ir iespējami, izmantojot bitkartes indeksus. ViltÄ«ba ir izmantot Ä£eometrisku attēlojumu, kas ieskauj jÅ«su koordinātu ar Ä£eometrisku figÅ«ru. Piemēram, S2 no Google. Ciparu jābÅ«t iespējai attēlot trÄ«s vai vairāku krustojoÅ”u lÄ«niju veidā, kuras var numurēt. Tādā veidā mēs varam pārvērst savu Ä£eovaicājumu vairākos vaicājumos ā€œgar atstarpiā€ (pa Ŕīm numurētajām lÄ«nijām).

Gatavi risinājumi

Es ceru, ka es jÅ«s nedaudz ieinteresēju, un tagad jÅ«su arsenālā ir vēl viens noderÄ«gs rÄ«ks. Ja jums kādreiz bÅ«s jādara kaut kas lÄ«dzÄ«gs Å”im, jÅ«s zināt, kā meklēt.

Tomēr ne visiem ir laiks, pacietÄ«ba vai resursi, lai izveidotu bitkartes indeksus no nulles. ÄŖpaÅ”i uzlabotas, piemēram, izmantojot SIMD.

Par laimi, ir vairāki gatavi risinājumi, kas jums palīdzēs.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā

RūkojoŔas bitkartes

Pirmkārt, ir tā pati rÅ«coŔā bitkartes bibliotēka, par kuru es jau runāju. Tajā ir visi nepiecieÅ”amie konteineri un bitu darbÄ«bas, kas jums bÅ«s nepiecieÅ”amas, lai izveidotu pilnvērtÄ«gu bitkartes indeksu.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Diemžēl Å”obrÄ«d neviena no Go implementācijām neizmanto SIMD, kas nozÄ«mē, ka Go implementācijas ir mazāk efektÄ«vas nekā, piemēram, C implementācijas.

Pilosa

Vēl viens produkts, kas var jums palÄ«dzēt, ir Pilosa DBMS, kam faktiski ir tikai bitkartes indeksi. Tas ir salÄ«dzinoÅ”i jauns risinājums, taču tas ļoti ātri iekaro cilvēku sirdis.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Pilosa iekŔēji izmanto rÅ«coÅ”as bitkartes un sniedz jums iespēju tās izmantot, vienkārÅ”o un izskaidro visas lietas, par kurām es runāju iepriekÅ”: grupÄ“Å”ana, diapazonā kodētas bitkartes, lauka jēdziens utt.

ApskatÄ«sim Pilosa izmantoÅ”anas piemēru, lai atbildētu uz jums jau zināmu jautājumu.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Piemērs ir ļoti lÄ«dzÄ«gs tam, ko redzējāt iepriekÅ”. Mēs izveidojam klientu Pilosa serverim, izveidojam indeksu un nepiecieÅ”amos laukus, pēc tam aizpildām savus laukus ar nejauÅ”iem datiem ar varbÅ«tÄ«bām un, visbeidzot, izpildām pazÄ«stamo vaicājumu.

Pēc tam laukā "dārgs" lietojam NOT, pēc tam krustojam rezultātu (vai UN to) ar lauku "terase" un lauku "rezervācijas". Un visbeidzot mēs iegūstam gala rezultātu.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Es ļoti ceru, ka pārskatāmā nākotnē Å”is jaunais indeksa veids parādÄ«sies arÄ« tādās DBVS kā MySQL un PostgreSQL - bitkartes indeksos.
Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā

Secinājums

Bitkartes indeksi programmā Go: meklējiet savvaļas ātrumā
Ja vēl neesi aizmigusi, paldies. Ierobežotā laika dēļ nācās Ä«si pieskarties daudzām tēmām, taču ceru, ka runa bija noderÄ«ga un varbÅ«t pat motivējoÅ”a.

Bitkartes indeksus ir labi zināt, pat ja jums tie paÅ”laik nav vajadzÄ«gi. Ä»aujiet tiem kļūt par vēl vienu rÄ«ku jÅ«su rÄ«ku komplektā.

Mēs esam apskatÄ«juÅ”i dažādus Go veiktspējas trikus un lietas, ar kurām Go kompilators vēl netiek galā. Bet tas ir absolÅ«ti noderÄ«gi zināt ikvienam Go programmētājam.

Tas ir viss, ko es gribēju jums pateikt. Paldies!

Avots: www.habr.com

Pievieno komentāru