Bitmap-indekse in Go: soek teen wilde spoed

Bitmap-indekse in Go: soek teen wilde spoed

inleiding

Ek het hierdie verslag in Engels gegee by die GopherCon Russia 2019-konferensie in Moskou en in Russies by 'n ontmoeting in Nizhny Novgorod. Ons praat van 'n bitmap-indeks - minder algemeen as B-boom, maar nie minder interessant nie. Deel opname toesprake by die konferensie in Engels en tekstranskripsies in Russies.

Ons sal kyk hoe 'n bitmap-indeks werk, wanneer dit beter is, wanneer dit slegter as ander indekse is, en in watter gevalle is dit aansienlik vinniger as hulle; Kom ons kyk watter gewilde DBBS'e reeds bitmap-indekse het; Kom ons probeer om ons eie in Go te skryf. En "vir nagereg" sal ons klaargemaakte biblioteke gebruik om ons eie supervinnige gespesialiseerde databasis te skep.

Ek hoop regtig dat my werke nuttig en interessant vir jou sal wees. Gaan!

Inleiding


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

Hi almal! Dit is ses in die aand en ons is almal supermoeg. Goeie tyd om oor vervelige databasisindeksteorie te praat, reg? Moenie bekommerd wees nie, ek sal hier en daar 'n paar reëls bronkode hê. 🙂

Alle grappies ter syde, die berig is propvol inligting, en ons het nie baie tyd nie. So kom ons begin.
Bitmap-indekse in Go: soek teen wilde spoed
Vandag sal ek oor die volgende praat:

  • wat is indekse;
  • wat is 'n bitmap-indeks;
  • waar dit gebruik word en waar dit NIE gebruik word nie en hoekom;
  • eenvoudige implementering in Go en 'n bietjie gesukkel met die samesteller;
  • effens minder eenvoudig, maar baie meer produktiewe implementering in Go assembler;
  • "probleme" van bitmap-indekse;
  • bestaande implementerings.

So, wat is indekse?

Bitmap-indekse in Go: soek teen wilde spoed

Die indeks is 'n aparte datastruktuur wat ons bykomend tot die hoofdata onderhou en bywerk. Dit word gebruik om die soektog te versnel. Sonder indekse sou soek vereis dat die data heeltemal deurgegaan word ('n proses wat volle skandering genoem word), en hierdie proses het lineêre algoritmiese kompleksiteit. Maar databasisse bevat gewoonlik groot hoeveelhede data en lineêre kompleksiteit is te stadig. Ideaal gesproke sou ons 'n logaritmiese of konstante een kry.

Dit is 'n uiters komplekse onderwerp, gevul met subtiliteite en afwykings, maar nadat ek na dekades van databasisontwikkeling en navorsing gekyk het, is ek bereid om te sê dat daar slegs 'n paar algemeen gebruikte benaderings is om databasisindekse te skep.

Bitmap-indekse in Go: soek teen wilde spoed

Die eerste benadering is om die soekruimte hiërargies te verminder, deur die soekruimte in kleiner dele te verdeel.

Ons doen dit gewoonlik deur verskillende soorte bome te gebruik. 'n Voorbeeld sou 'n groot boks materiaal in jou kas wees wat kleiner bokse materiaal bevat wat in verskillende onderwerpe verdeel is. As jy materiaal nodig het, sal jy dit waarskynlik soek in 'n boks wat sê "Materials" eerder as een wat sê "Koekies," reg?

Bitmap-indekse in Go: soek teen wilde spoed

Die tweede benadering is om onmiddellik die gewenste element of groep elemente te kies. Ons doen dit in hash-kaarte of omgekeerde indekse. Die gebruik van hash-kaarte stem baie ooreen met die vorige voorbeeld, maar in plaas van 'n boks bokse, het jy 'n klomp klein boksies met finale items in jou kas.

Bitmap-indekse in Go: soek teen wilde spoed

Die derde benadering is om die behoefte aan soek uit te skakel. Ons doen dit met behulp van Bloom-filters of koekoekfilters. Die eerstes gee onmiddellik 'n antwoord, wat jou red om te soek.

Bitmap-indekse in Go: soek teen wilde spoed

Die laaste benadering is om ten volle gebruik te maak van al die krag wat moderne hardeware ons gee. Dit is presies wat ons doen in bitmap-indekse. Ja, wanneer ons dit gebruik, moet ons soms deur die hele indeks gaan, maar ons doen dit baie doeltreffend.

Soos ek gesê het, is die onderwerp van databasis-indekse groot en vol kompromieë. Dit beteken dat ons soms verskeie benaderings gelyktydig kan gebruik: as ons die soektog nog meer moet bespoedig, of as ons alle moontlike soektipes moet dek.

Vandag sal ek praat oor die minste bekende benadering van hierdie - bitmap-indekse.

Wie is ek om oor hierdie onderwerp te praat?

Bitmap-indekse in Go: soek teen wilde spoed

Ek werk as 'n spanleier by Badoo (miskien is jy meer vertroud met ons ander produk, Bumble). Ons het reeds meer as 400 miljoen gebruikers regoor die wêreld en baie kenmerke wat die beste pasmaat vir hulle kies. Ons doen dit deur gebruik te maak van pasgemaakte dienste, insluitend bitmap-indekse.

So, wat is 'n bitmap-indeks?

Bitmap-indekse in Go: soek teen wilde spoed
Bitmap-indekse, soos die naam aandui, gebruik bitmaps of bitsets om 'n soekindeks te implementeer. Vanuit 'n voëlkyk-aansig bestaan ​​hierdie indeks uit een of meer sulke bitmaps wat enige entiteite (soos mense) en hul eienskappe of parameters (ouderdom, oogkleur, ens.) verteenwoordig, en 'n algoritme wat bis-bewerkings gebruik (EN, OF, NIE ) om die soektog te beantwoord.
Bitmap-indekse in Go: soek teen wilde spoed
Ons word vertel dat bitmap-indekse die beste geskik is en baie werksaam is vir gevalle waar daar soektogte is wat navrae oor baie lae kardinaliteitkolomme kombineer (dink "oogkleur" of "huwelikstatus" teenoor iets soos "afstand vanaf middestad"). Maar ek sal later wys dat hulle ook goed werk vir hoë kardinaliteit kolomme.

Kom ons kyk na die eenvoudigste voorbeeld van 'n bitmap-indeks.
Bitmap-indekse in Go: soek teen wilde spoed
Stel jou voor dat ons 'n lys van Moskou-restaurante het met binêre eienskappe soos hierdie:

  • naby metro;
  • daar is privaat parkeerplek;
  • daar is 'n stoep (het terras);
  • jy kan 'n tafel bespreek (aanvaar besprekings);
  • geskik vir vegetariërs (vegan vriendelik);
  • duur (duur).

Bitmap-indekse in Go: soek teen wilde spoed
Kom ons gee vir elke restaurant 'n rynommer wat vanaf 0 begin en ken geheue toe vir 6 bitmaps (een vir elke eienskap). Ons sal dan hierdie bitkaarte invul, afhangende van of die restaurant hierdie eiendom het of nie. As restaurant 4 'n stoep het, sal bit nr. 4 in die "het 'n stoep" bitmap op 1 gestel word (as daar geen stoep is nie, dan op 0).
Bitmap-indekse in Go: soek teen wilde spoed
Nou het ons die eenvoudigste bitmap-indeks moontlik, en ons kan dit gebruik om navrae soos:

  • "Wys vir my vegetaries-vriendelike restaurante";
  • "Wys my goedkoop restaurante met 'n stoep waar jy 'n tafel kan bespreek."

Bitmap-indekse in Go: soek teen wilde spoed
Bitmap-indekse in Go: soek teen wilde spoed
Hoe? Kom ons kyk. Die eerste versoek is baie eenvoudig. Al wat ons hoef te doen is om die "vegetariese vriendelike" bitmap te neem en dit te verander in 'n lys van restaurante waarvan die stukkies ontbloot is.
Bitmap-indekse in Go: soek teen wilde spoed
Bitmap-indekse in Go: soek teen wilde spoed
Die tweede versoek is 'n bietjie meer ingewikkeld. Ons moet die NOT bitmap op die "duur" bitmap gebruik om 'n lys van goedkoop restaurante te kry, dan EN dit met die "can I book a table" bitmap en EN die resultaat met die "there is a veranda" bitmap. Die gevolglike bitmap sal 'n lys van ondernemings bevat wat aan al ons kriteria voldoen. In hierdie voorbeeld is dit slegs die Yunost-restaurant.
Bitmap-indekse in Go: soek teen wilde spoed
Bitmap-indekse in Go: soek teen wilde spoed
Daar is baie teorie betrokke, maar moenie bekommerd wees nie, ons sal die kode binnekort sien.

Waar word bitmap-indekse gebruik?

Bitmap-indekse in Go: soek teen wilde spoed
As jy bitmap-indekse Google, sal 90% van die antwoorde op een of ander manier met Oracle DB verband hou. Maar ander DBBS'e ondersteun seker ook so 'n cool ding, nie waar nie? Nie regtig nie.

Kom ons gaan deur die lys van hoofverdagtes.
Bitmap-indekse in Go: soek teen wilde spoed
MySQL ondersteun nog nie bitmap-indekse nie, maar daar is 'n voorstel wat voorstel om hierdie opsie by te voeg (https://dev.mysql.com/worklog/task/?id=1524).

PostgreSQL ondersteun nie bitmap-indekse nie, maar gebruik eenvoudige bitmaps en bis-bewerkings om soekresultate oor verskeie ander indekse te kombineer.

Tarantool het bitset-indekse en ondersteun eenvoudige soektogte daarop.

Redis het eenvoudige bitvelde (https://redis.io/commands/bitfield) sonder die vermoë om na hulle te soek.

MongoDB ondersteun nog nie bitmap-indekse nie, maar daar is ook 'n voorstel wat voorstel dat hierdie opsie bygevoeg word https://jira.mongodb.org/browse/SERVER-1723

Elasticsearch gebruik bitmaps intern (https://www.elastic.co/blog/frame-of-reference-and-roaring-bitmaps).

Bitmap-indekse in Go: soek teen wilde spoed

  • Maar 'n nuwe buurman het in ons huis verskyn: Pilosa. Dit is 'n nuwe nie-relasionele databasis wat in Go geskryf is. Dit bevat slegs bitmap-indekse en baseer alles daarop. Ons sal 'n bietjie later daaroor praat.

Implementering in Go

Maar hoekom word bitmap-indekse so min gebruik? Voordat ek hierdie vraag beantwoord, wil ek jou graag wys hoe om 'n baie eenvoudige bitmap-indeks in Go te implementeer.
Bitmap-indekse in Go: soek teen wilde spoed
Bitmaps is in wese net stukke data. In Go, kom ons gebruik byte-skywe hiervoor.

Ons het een bitmap vir een restaurantkenmerk, en elke stukkie in die bitmap dui aan of 'n spesifieke restaurant hierdie eienskap het of nie.
Bitmap-indekse in Go: soek teen wilde spoed
Ons sal twee helperfunksies benodig. Een sal gebruik word om ons bitmaps met ewekansige data te vul. Willekeurig, maar met 'n sekere waarskynlikheid dat die restaurant elke eiendom het. Ek glo byvoorbeeld dat daar baie min restaurante in Moskou is waar jy nie 'n tafel kan bespreek nie, en dit lyk vir my of sowat 20% van die instansies geskik is vir vegetariërs.

Die tweede funksie sal die bitmap omskep in 'n lys restaurante.
Bitmap-indekse in Go: soek teen wilde spoed
Bitmap-indekse in Go: soek teen wilde spoed
Om die navraag "Wys my goedkoop restaurante wat 'n patio het en besprekings kan maak" te beantwoord, benodig ons twee bis-bewerkings: NIE en EN.

Ons kan ons kode 'n bietjie vereenvoudig deur die meer komplekse EN NIE-operateur te gebruik.

Ons het funksies vir elk van hierdie operasies. Beide van hulle gaan deur die snye, neem die ooreenstemmende elemente van elkeen, kombineer dit met 'n bietjie bewerking en plaas die resultaat in die gevolglike sny.
Bitmap-indekse in Go: soek teen wilde spoed
En nou kan ons ons bitmaps en funksies gebruik om die soektog te beantwoord.
Bitmap-indekse in Go: soek teen wilde spoed
Werkverrigting is nie so hoog nie, al is die funksies baie eenvoudig en ons het baie geld gespaar deur nie 'n nuwe gevolglike sny terug te gee elke keer as die funksie opgeroep is nie.

Nadat ek 'n bietjie profilering met pprof gedoen het, het ek opgemerk dat die Go-samesteller een baie eenvoudige maar baie belangrike optimalisering ontbreek: funksie-inlyn.
Bitmap-indekse in Go: soek teen wilde spoed
Die feit is dat die Go-samesteller verskriklik bang is vir lusse wat deur skywe gaan, en weier kategories om funksies wat sulke lusse bevat, inlyn te maak.
Bitmap-indekse in Go: soek teen wilde spoed
Maar ek is nie bang nie en ek kan die samesteller flous deur goto in plaas van 'n lus te gebruik, soos in die goeie ou dae.

Bitmap-indekse in Go: soek teen wilde spoed
Bitmap-indekse in Go: soek teen wilde spoed

En, soos jy kan sien, sal die samesteller nou gelukkig ons funksie inlyn! As gevolg hiervan slaag ons daarin om ongeveer 2 mikrosekondes te bespaar. Nie sleg nie!

Bitmap-indekse in Go: soek teen wilde spoed

Die tweede knelpunt is maklik om te sien as jy noukeurig na die samestellingsuitset kyk. Die samesteller het 'n snygrenskontrole reg binne ons warmste lus bygevoeg. Die feit is dat Go 'n veilige taal is, die samesteller is bang dat my drie argumente (drie snye) van verskillende groottes is. Daar sal immers 'n teoretiese moontlikheid wees van die voorkoms van 'n sogenaamde bufferoorloop.

Kom ons stel die samesteller gerus deur dit te wys dat alle skywe dieselfde grootte is. Ons kan dit doen deur 'n eenvoudige tjek aan die begin van ons funksie by te voeg.
Bitmap-indekse in Go: soek teen wilde spoed
As die samesteller dit sien, slaan die samesteller gelukkig die tjek oor, en ons spaar uiteindelik nog 500 nanosekondes.

Groot butches

Goed, ons het daarin geslaag om 'n mate van prestasie uit ons eenvoudige implementering te druk, maar hierdie resultaat is eintlik baie erger as wat moontlik is met huidige hardeware.

Al wat ons doen is basiese bis-bewerkings, en ons verwerkers voer dit baie doeltreffend uit. Maar ongelukkig "voed" ons ons verwerker met baie klein stukkies werk. Ons funksies voer bewerkings op 'n greep-vir-greep basis uit. Ons kan ons kode baie maklik aanpas om met 8-grepe-stukke te werk deur UInt64-skywe te gebruik.

Bitmap-indekse in Go: soek teen wilde spoed

Soos u kan sien, het hierdie klein verandering ons program agt keer versnel deur die bondelgrootte met agt keer te vergroot. Die wins kan gesê word dat dit lineêr is.

Bitmap-indekse in Go: soek teen wilde spoed

Implementering in assembler

Bitmap-indekse in Go: soek teen wilde spoed
Maar dit is nie die einde nie. Ons verwerkers kan werk met stukke van 16, 32 en selfs 64 grepe. Sulke "breë" bewerkings word enkel-instruksie meervoudige data (SIMD; een instruksie, baie data) genoem, en die proses om kode te transformeer sodat dit sulke bewerkings gebruik, word vektorisering genoem.

Ongelukkig is die Go-samesteller ver van uitstekend met vektorisering. Tans is die enigste manier om Go-kode te vektoriseer om hierdie bewerkings met die hand te neem en te plaas deur Go assembler te gebruik.

Bitmap-indekse in Go: soek teen wilde spoed

Go assembler is 'n vreemde dier. Jy weet waarskynlik dat samestellingstaal iets is wat sterk gekoppel is aan die argitektuur van die rekenaar waarvoor jy skryf, maar dit is nie die geval in Go nie. Go assembler is meer soos 'n IRL (intermediêre verteenwoordigingstaal) of intermediêre taal: dit is feitlik platformonafhanklik. Rob Pike het 'n uitstekende vertoning gelewer rapporteer oor hierdie onderwerp etlike jare gelede by GopherCon in Denver.

Boonop gebruik Go 'n ongewone Plan 9-formaat, wat verskil van die algemeen aanvaarde AT&T- en Intel-formate.
Bitmap-indekse in Go: soek teen wilde spoed
Dit is veilig om te sê dat dit nie die lekkerste is om Go assembler met die hand te skryf nie.

Maar gelukkig is daar reeds twee hoëvlak-instrumente wat ons help om Go assembler te skryf: PeachPy en avo. Albei nutsprogramme genereer Go assembler vanaf hoërvlakkode wat onderskeidelik in Python en Go geskryf is.
Bitmap-indekse in Go: soek teen wilde spoed
Hierdie nutsprogramme vereenvoudig dinge soos registertoewysing, skryflusse en vereenvoudig oor die algemeen die proses om in die wêreld van samestellingsprogrammering in Go te kom.

Ons sal avo gebruik, so ons programme sal amper gewone Go-programme wees.
Bitmap-indekse in Go: soek teen wilde spoed
Dit is hoe die eenvoudigste voorbeeld van 'n avo-program lyk. Ons het 'n hoof()-funksie, wat die Add()-funksie binne homself definieer, waarvan die betekenis is om twee getalle by te tel. Daar is helperfunksies hier om parameters by naam te kry en een van die gratis en geskikte verwerkerregisters te kry. Elke verwerkerbewerking het 'n ooreenstemmende funksie op avo, soos gesien in ADDQ. Laastens sien ons 'n helperfunksie vir die stoor van die resulterende waarde.
Bitmap-indekse in Go: soek teen wilde spoed
Deur gaan genereer te roep, sal ons die program op avo uitvoer en gevolglik sal twee lêers gegenereer word:

  • add.s met die gevolglike kode in Go assembler;
  • stub.go met funksieopskrifte om die twee wêrelde te verbind: Go en assembler.

Bitmap-indekse in Go: soek teen wilde spoed
Noudat ons gesien het wat avo doen en hoe, kom ons kyk na ons funksies. Ek het beide skalêre en vektor (SIMD) weergawes van die funksies geïmplementeer.

Kom ons kyk eers na die skalêre weergawes.
Bitmap-indekse in Go: soek teen wilde spoed
Soos in die vorige voorbeeld, vra ons vir 'n gratis en geldige algemene doelregister, ons hoef nie afwykings en groottes vir die argumente te bereken nie. avo doen dit alles vir ons.
Bitmap-indekse in Go: soek teen wilde spoed
Ons het voorheen etikette en goto (of springs) gebruik om werkverrigting te verbeter en die Go-samesteller te mislei, maar nou doen ons dit van die begin af. Die punt is dat siklusse 'n hoër-vlak konsep is. In assembler het ons net etikette en spronge.
Bitmap-indekse in Go: soek teen wilde spoed
Die oorblywende kode behoort reeds bekend en verstaanbaar te wees. Ons boots 'n lus na met byskrifte en spronge, neem 'n klein stukkie data uit ons twee skywe, kombineer dit met 'n bietjie bewerking (EN NIE in hierdie geval NIE) en plaas dan die resultaat in die resulterende sny. Almal.
Bitmap-indekse in Go: soek teen wilde spoed
Dit is hoe die finale samesteller-kode lyk. Ons hoef nie afwykings en groottes (in groen uitgelig) te bereken of tred te hou met die registers wat gebruik is (in rooi uitgelig nie).
Bitmap-indekse in Go: soek teen wilde spoed
As ons die prestasie van die samestellingstaalimplementering vergelyk met die prestasie van die beste implementering in Go, sal ons sien dat dit dieselfde is. En dit word verwag. Ons het immers niks spesiaals gedoen nie – ons het net weergegee wat 'n Go-samesteller sou doen.

Ongelukkig kan ons nie die samesteller dwing om ons funksies wat in samestellende taal geskryf is, inlyn te maak nie. Die Go-samesteller het tans nie so 'n kenmerk nie, alhoewel daar al 'n geruime tyd 'n versoek was om dit by te voeg.

Dit is hoekom dit onmoontlik is om enige voordeel te trek uit klein funksies in samestellende taal. Ons moet óf groot funksies skryf, óf die nuwe wiskunde/bis-pakket gebruik, óf die samestellertaal omseil.

Kom ons kyk nou na die vektorweergawes van ons funksies.
Bitmap-indekse in Go: soek teen wilde spoed
Vir hierdie voorbeeld het ek besluit om AVX2 te gebruik, so ons sal bewerkings gebruik wat op 32-grepe stukke werk. Die struktuur van die kode is baie soortgelyk aan die skalêre weergawe: laai parameters, vra vir 'n gratis gedeelde register, ens.
Bitmap-indekse in Go: soek teen wilde spoed
Een innovasie is dat breër vektorbewerkings spesiale wye registers gebruik. In die geval van 32-grepe stukke, is dit registers wat met Y voorafgaan. Dit is hoekom jy die YMM() funksie in die kode sien. As ek AVX-512 met 64-bis-stukke gebruik, sou die voorvoegsel Z wees.

Die tweede innovasie is dat ek besluit het om 'n optimalisering genaamd lus ontrol te gebruik, wat beteken om agt lusbewerkings met die hand te doen voordat ek na die begin van die lus spring. Hierdie optimalisering verminder die aantal takke in die kode, en word beperk deur die aantal gratis registers wat beskikbaar is.
Bitmap-indekse in Go: soek teen wilde spoed
Wel, wat van prestasie? Sy is mooi! Ons het 'n versnelling van ongeveer sewe keer behaal in vergelyking met die beste Go-oplossing. Indrukwekkend, reg?
Bitmap-indekse in Go: soek teen wilde spoed
Maar selfs hierdie implementering kan moontlik versnel word deur AVX-512, prefetching of 'n JIT (net-in-tyd samesteller) vir die navraagskeduleerder te gebruik. Maar dit is beslis 'n onderwerp vir 'n aparte verslag.

Probleme met bitmap-indekse

Noudat ons reeds gekyk het na 'n eenvoudige implementering van 'n bitmap-indeks in Go en 'n baie meer produktiewe een in samestellende taal, kom ons praat uiteindelik oor hoekom bitmap-indekse so min gebruik word.
Bitmap-indekse in Go: soek teen wilde spoed
Ouer vraestelle noem drie probleme met bitmap-indekse, maar nuwer vraestelle en ek argumenteer dat dit nie meer relevant is nie. Ons sal nie diep in elkeen van hierdie probleme duik nie, maar oppervlakkig daarna kyk.

Die probleem van hoë kardinaliteit

Ons word dus vertel dat bitmap-indekse slegs geskik is vir velde met lae kardinaliteit, dit wil sê dié wat min waardes het (byvoorbeeld geslag of oogkleur), en die rede is dat die gewone voorstelling van sulke velde (een) bit per waarde) in die geval van hoë kardinaliteit, sal dit te veel spasie opneem en boonop sal hierdie bitmap-indekse swak (selde) gevul wees.
Bitmap-indekse in Go: soek teen wilde spoed
Bitmap-indekse in Go: soek teen wilde spoed
Soms kan ons 'n ander voorstelling gebruik, soos die standaard een wat ons gebruik om getalle voor te stel. Maar dit was die koms van kompressie-algoritmes wat alles verander het. Oor die afgelope dekades het wetenskaplikes en navorsers vorendag gekom met 'n groot aantal kompressie-algoritmes vir bitmaps. Hul grootste voordeel is dat dit nie nodig is om bitmaps te dekomprimeer om bis-bewerkings uit te voer nie - ons kan bis-bewerkings direk op saamgeperste bitmaps uitvoer.
Bitmap-indekse in Go: soek teen wilde spoed
Onlangs het hibriede benaderings begin verskyn, soos brullende bitmaps. Hulle gebruik gelyktydig drie verskillende voorstellings vir bitmaps - bitmaps self, skikkings en sogenaamde bit runs - en balanseer tussen hulle om werkverrigting te maksimeer en geheueverbruik te minimaliseer.

Jy kan brullende bitmaps vind in die gewildste toepassings. Daar is reeds 'n groot aantal implementerings vir 'n wye verskeidenheid programmeertale, insluitend meer as drie implementerings vir Go.
Bitmap-indekse in Go: soek teen wilde spoed
Nog 'n benadering wat ons kan help om hoë kardinaliteit te hanteer, word binning genoem. Stel jou voor jy het 'n veld wat 'n persoon se lengte voorstel. Hoogte is 'n drywende puntgetal, maar ons mense dink nie so daaraan nie. Vir ons is daar geen verskil tussen hoogte 185,2 cm en 185,3 cm nie.

Dit blyk dat ons soortgelyke waardes binne 1 cm in groepe kan groepeer.

En as ons ook weet dat baie min mense korter as 50 cm en langer as 250 cm is, dan kan ons in wese 'n veld met oneindige kardinaliteit verander in 'n veld met 'n kardinaliteit van ongeveer 200 waardes.

Natuurlik, indien nodig, kan ons daarna addisionele filtering doen.

Hoë bandwydte probleem

Die volgende probleem met bitmap-indekse is dat dit baie duur kan wees om dit op te dateer.

Databasisse moet data kan opdateer terwyl moontlik honderde ander navrae die data deursoek. Ons het slotte nodig om probleme met gelyktydige datatoegang of ander deelprobleme te vermy. En waar daar een groot slot is, is daar 'n probleem - slotkonflik, wanneer hierdie slot 'n bottelnek word.
Bitmap-indekse in Go: soek teen wilde spoed
Hierdie probleem kan opgelos of omseil word deur die gebruik van sharding of die gebruik van weergawe-indekse.

Sharing is 'n eenvoudige en bekende ding. Jy kan 'n bitmap-indeks versplinter soos enige ander data. In plaas van een groot slot, sal jy 'n klomp klein slotte kry en sodoende ontslae raak van slotkonflik.

Die tweede manier om die probleem op te los, is om weergawes van indekse te gebruik. Jy kan een kopie van die indeks hê wat jy gebruik om te soek of te lees, en een wat jy gebruik om te skryf of op te dateer. En een keer in 'n sekere tydperk (byvoorbeeld een keer elke 100 ms of 500 ms) dupliseer jy hulle en ruil hulle om. Natuurlik is hierdie benadering slegs van toepassing in gevalle waar jou aansoek 'n effens sloerende soekindeks kan hanteer.

Hierdie twee benaderings kan gelyktydig gebruik word: jy kan 'n versnipperde weergawe-indeks hê.

Meer komplekse navrae

Die laaste probleem met bitmap-indekse is dat ons vertel word dat hulle nie goed geskik is vir meer komplekse tipes navrae, soos spannavrae nie.

Inderdaad, as jy daaraan dink, is bietjie bewerkings soos EN, OF, ens. nie baie geskik vir navrae a la "Wys my hotelle met kamertariewe tussen 200 en 300 dollar per nag."
Bitmap-indekse in Go: soek teen wilde spoed
'n Naïewe en baie onwyse oplossing sou wees om die resultate vir elke dollarwaarde te neem en dit te kombineer met 'n bitsgewyse OF-operasie.
Bitmap-indekse in Go: soek teen wilde spoed
'n Effens beter oplossing sou wees om groepering te gebruik. Byvoorbeeld, in groepe van 50 dollar. Dit sal ons proses met 50 keer versnel.

Maar die probleem word ook maklik opgelos deur 'n aansig te gebruik wat spesifiek vir hierdie tipe versoek geskep is. In wetenskaplike artikels word dit reeksgekodeerde bitmaps genoem.
Bitmap-indekse in Go: soek teen wilde spoed
In hierdie voorstelling stel ons nie net een bietjie vir een of ander waarde nie (byvoorbeeld 200), maar stel hierdie waarde en alles hoër. 200 en hoër. Dieselfde vir 300:300 en hoër. En so aan.

Deur hierdie voorstelling te gebruik, kan ons hierdie soort soeknavraag beantwoord deur die indeks net twee keer te deurkruis. Eerstens sal ons 'n lys van hotelle kry waar die kamer minder of $300 kos, en dan sal ons diegene verwyder waar die kamer kos minder of $199 is. Gereed.
Bitmap-indekse in Go: soek teen wilde spoed
Jy sal verbaas wees, maar selfs geonavrae is moontlik met behulp van bitmap-indekse. Die truuk is om 'n meetkundige voorstelling te gebruik wat jou koördinaat met 'n meetkundige figuur omring. Byvoorbeeld, S2 van Google. Die figuur moet moontlik wees om voor te stel in die vorm van drie of meer snylyne wat genommer kan word. Op hierdie manier kan ons ons geoquery omskep in verskeie navrae "langs die gaping" (langs hierdie genommerde lyne).

Klaar oplossings

Ek hoop ek het jou 'n bietjie geïnteresseerd en jy het nou nog 'n nuttige hulpmiddel in jou arsenaal. As jy ooit so iets moet doen, sal jy weet watter kant toe om te kyk.

Nie almal het egter die tyd, geduld of hulpbronne om bitmap-indekse van nuuts af te skep nie. Veral meer gevorderdes, met behulp van SIMD, byvoorbeeld.

Gelukkig is daar verskeie gereedgemaakte oplossings om jou te help.
Bitmap-indekse in Go: soek teen wilde spoed

Brullende bitmaps

Eerstens is daar dieselfde brullende bitmaps-biblioteek waaroor ek reeds gepraat het. Dit bevat al die nodige houers en bis-bewerkings wat jy nodig het om 'n volwaardige bitmap-indeks te skep.
Bitmap-indekse in Go: soek teen wilde spoed
Ongelukkig, op die oomblik, gebruik geen van die Go-implementerings SIMD nie, wat beteken dat Go-implementerings byvoorbeeld minder presteer as C-implementerings.

Pilosa

Nog 'n produk wat jou kan help, is die Pilosa DBMS, wat in werklikheid net bitmap-indekse het. Dit is 'n relatief nuwe oplossing, maar dit wen harte met groot spoed.
Bitmap-indekse in Go: soek teen wilde spoed
Pilosa gebruik brullende bitmaps intern en gee jou die vermoë om dit te gebruik, vereenvoudig en verduidelik al die dinge waaroor ek hierbo gepraat het: groepering, reeksgekodeerde bitmaps, die konsep van 'n veld, ens.

Kom ons kyk vinnig na 'n voorbeeld van die gebruik van Pilosa om 'n vraag te beantwoord waarmee jy reeds vertroud is.
Bitmap-indekse in Go: soek teen wilde spoed
Die voorbeeld is baie soortgelyk aan wat jy voorheen gesien het. Ons skep 'n kliënt na die Pilosa-bediener, skep 'n indeks en die nodige velde, vul dan ons velde met ewekansige data met waarskynlikhede en voer uiteindelik die bekende navraag uit.

Daarna gebruik ons ​​NIE op die "duur" veld, sny dan die resultaat (of EN dit) met die "terras" veld en met die "besprekings" veld. En uiteindelik kry ons die finale resultaat.
Bitmap-indekse in Go: soek teen wilde spoed
Ek hoop regtig dat hierdie nuwe tipe indeks in die afsienbare toekoms ook in DBMS'e soos MySQL en PostgreSQL sal verskyn - bitmap-indekse.
Bitmap-indekse in Go: soek teen wilde spoed

Gevolgtrekking

Bitmap-indekse in Go: soek teen wilde spoed
As jy nog nie aan die slaap geraak het nie, dankie. Ek moes baie onderwerpe kortliks aanraak weens beperkte tyd, maar ek hoop die praatjie was nuttig en dalk selfs motiverend.

Bitmap-indekse is goed om van te weet, selfs al het jy dit nie nou nodig nie. Laat hulle nog 'n hulpmiddel in jou gereedskapkas wees.

Ons het na verskeie prestasie-truuks vir Go gekyk en dinge wat die Go-samesteller nog nie baie goed hanteer nie. Maar dit is absoluut nuttig vir elke Go-programmeerder om te weet.

Dis al wat ek vir jou wou vertel. Dankie!

Bron: will.com

Voeg 'n opmerking