Indici Bitmap in Go: ricerca à velocità salvatica

Indici Bitmap in Go: ricerca à velocità salvatica

introduzione

Aghju datu stu rapportu in inglese à a cunferenza GopherCon Russia 2019 in Mosca è in russo in un meeting in Nizhny Novgorod. Parlemu di un indice bitmap - menu cumuni cà B-tree, ma micca menu interessante. A spartera arregistramentu discorsi à a cunferenza in inglese è trascrizioni di testu in russo.

Fighjemu cumu funziona un indice bitmap, quandu hè megliu, quandu hè peghju di l'altri indici, è in quali casi hè significativamente più veloce di elli; Videmu quali DBMS populari anu digià indici bitmap; Pruvemu di scrive u nostru propiu in Go. È "per dessert" useremu biblioteche pronti per creà a nostra propria basa di dati specializata super-rapida.

Spergu veramente chì e mo opere seranu utili è interessanti per voi. Vai !

Introduzione


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

Salut à tutti ! Sò sei di sera è simu tutti super stanchi. Un bellu tempu per parlà di a teoria di l'indici di basa di dati noiosa, nò? Ùn vi preoccupate, aghju un paru di linee di codice fonte quì è quì. 🙂

Tutti i scherzi à parte, u rapportu hè pienu d'infurmazioni, è ùn avemu micca assai tempu. Allora cuminciamu.
Indici Bitmap in Go: ricerca à velocità salvatica
Oghje parleraghju di i seguenti:

  • ciò chì sò indici;
  • ciò chì hè un indice bitmap;
  • induve hè usatu è induve ùn hè micca usatu è perchè;
  • implementazione simplice in Go è un pocu di lotta cù u compilatore;
  • implementazione un pocu menu simplice, ma assai più produtiva in Go assembler;
  • "prublemi" di l'indici bitmap;
  • implementazioni esistenti.

Allora chì sò l'indici?

Indici Bitmap in Go: ricerca à velocità salvatica

L'indici hè una struttura di dati separata chì mantenemu è aghjurnà in più di e dati principali. Hè adupratu per accelerà a ricerca. Senza indici, a ricerca avaristi bisognu di passà per e dati cumpletamente (un prucessu chjamatu scansione completa), è questu prucessu hà una cumplessità algoritmica lineale. Ma e basa di dati di solitu cuntenenu quantità enormi di dati è a cumplessità lineale hè troppu lenta. Ideale, averemu un logaritmicu o custante.

Questu hè un tema assai cumplessu, pienu di suttilità è di scambii, ma dopu avè vistu decennii di sviluppu di basa di dati è ricerca, sò dispostu à dì chì ci sò solu uni pochi di approcci largamente usati per creà indici di basa di dati.

Indici Bitmap in Go: ricerca à velocità salvatica

U primu approcciu hè di riduce hierarchicamente u spaziu di ricerca, dividendu u spaziu di ricerca in parti più chjuche.

Di solitu facemu questu utilizendu diversi tipi d'arburi. Un esempiu seria una grande scatula di materiali in u vostru armariu chì cuntene scatuli più chjuchi di materiali divisi in temi diffirenti. Sè avete bisognu di materiali, probabilmente li cercherete in una casella chì dice "Materiali" invece di quellu chì dice "Cookies", nò?

Indici Bitmap in Go: ricerca à velocità salvatica

U sicondu approcciu hè di selezziunate immediatamente l'elementu desideratu o gruppu di elementi. Facemu questu in carte hash o indici inversi. L'usu di mape di hash hè assai simili à l'esempiu precedente, ma invece di una scatula di scatuli, avete una mansa di scatuli di articuli finali in u vostru armariu.

Indici Bitmap in Go: ricerca à velocità salvatica

U terzu approcciu hè di eliminà a necessità di ricerca. Facemu questu utilizendu filtri Bloom o filtri di cuccu. I primi dà una risposta istantaneamente, salvenendu da avè a ricerca.

Indici Bitmap in Go: ricerca à velocità salvatica

L'ultimu approcciu hè di fà un usu pienu di tuttu u putere chì u hardware mudernu ci dà. Questu hè esattamente ciò chì facemu in l'indici bitmap. Iè, quandu l'utilizanu avemu qualchì volta bisognu di passà per tuttu l'indici, ma u facemu in modu super efficiente.

Comu dissi, u tema di l'indici di basa di dati hè vastu è pienu di cumprumessi. Questu significa chì qualchì volta pudemu usà parechji approcci à u stessu tempu: s'ellu ci vole à accelerà a ricerca ancu di più, o s'ellu ci vole à copre tutti i tipi di ricerca pussibuli.

Oghje parleraghju di l'approcciu menu cunnisciutu di questi - indici bitmap.

Quale sò eiu per parlà nantu à stu tema ?

Indici Bitmap in Go: ricerca à velocità salvatica

U travagliu cum'è un capu di squadra in Badoo (forse site più familiarizatu cù u nostru altru pruduttu, Bumble). Avemu digià più di 400 milioni d'utilizatori in u mondu è parechje funziunalità chì selezziunate u megliu match per elli. Facemu questu utilizendu servizii persunalizati, cumpresi indici bitmap.

Allora chì hè un indice bitmap?

Indici Bitmap in Go: ricerca à velocità salvatica
L'indici di bitmap, cum'è u nome suggerisce, utilizanu bitmaps o bitsets per implementà un indici di ricerca. Da una vista d'ochju, stu indice hè custituitu da unu o più tali bitmaps chì rapprisentanu ogni entità (cum'è e persone) è e so proprietà o paràmetri (età, culore di l'ochji, etc.), è un algoritmu chì usa operazioni di bit (AND, OR, NOT). ) per risponde à a dumanda di ricerca.
Indici Bitmap in Go: ricerca à velocità salvatica
Ci hè dettu chì l'indici di bitmap sò più adattati è assai performanti per i casi induve ci sò e ricerche chì combinanu e dumande in parechje colonne di cardinalità bassa (pensate "culore d'ochji" o "statu civile" versus qualcosa cum'è "distanza da u centru di a cità"). Ma dimustraraghju più tardi chì travaglianu bè ancu per e colonne di alta cardinalità.

Fighjemu l'esempiu più simplice di un indice bitmap.
Indici Bitmap in Go: ricerca à velocità salvatica
Imagine chì avemu una lista di ristoranti di Mosca cù proprietà binari cum'è queste:

  • vicinu à u metro;
  • ci hè parcheghju privatu;
  • ci hè una veranda (hà una terrazza);
  • pudete riservà una tavola (accetta riservazioni);
  • adattatu per i vegetariani (vegan friendly);
  • caru (caru).

Indici Bitmap in Go: ricerca à velocità salvatica
Demu à ogni ristorante un numeru di sequenza partendu da 0 è assignemu memoria per 6 bitmaps (una per ogni caratteristica). Pupularemu dopu sti bitmaps secondu chì u ristorante hà sta pruprietà o micca. Se u ristorante 4 hà una veranda, allora u bit No. 4 in u bitmap "hà una veranda" serà stabilitu à 1 (se ùn ci hè micca veranda, allora à 0).
Indici Bitmap in Go: ricerca à velocità salvatica
Avà avemu l'indice bitmap più simplice pussibule, è pudemu usà per risponde à e dumande cum'è:

  • "Mostrami i ristoranti vegetariani";
  • "Mostrami ristoranti economici cun veranda induve pudete riservà una tavola".

Indici Bitmap in Go: ricerca à velocità salvatica
Indici Bitmap in Go: ricerca à velocità salvatica
Cumu? Fighjemu un ochju. A prima dumanda hè assai sèmplice. Tuttu ciò chì avemu da fà hè di piglià u bitmap "vegetarian friendly" è trasfurmà in una lista di ristoranti chì i pezzi sò esposti.
Indici Bitmap in Go: ricerca à velocità salvatica
Indici Bitmap in Go: ricerca à velocità salvatica
A seconda dumanda hè un pocu più cumplicata. Avemu bisognu di usà u bitmap NOT nantu à u bitmap "caru" per ottene una lista di ristoranti di prezzu, allora AND it with the "possu riservà una tavola" bitmap è AND u risultatu cù u bitmap "ci hè una veranda". U bitmap resultante cuntene una lista di stabilimenti chì risponde à tutti i nostri criteri. In questu esempiu, questu hè solu u ristorante Yunost.
Indici Bitmap in Go: ricerca à velocità salvatica
Indici Bitmap in Go: ricerca à velocità salvatica
Ci hè assai teorija implicata, ma ùn vi preoccupate, avemu da vede u codice assai prestu.

Induve sò usati l'indici bitmap?

Indici Bitmap in Go: ricerca à velocità salvatica
Se Google indici bitmap, 90% di e risposte seranu ligati à Oracle DB in una manera o l'altru. Ma altri DBMS probabilmente sustenenu ancu una cosa cusì bella, nò? Micca essatamente.

Andemu à traversu a lista di i principali suspettati.
Indici Bitmap in Go: ricerca à velocità salvatica
MySQL ùn sustene ancu l'indici bitmap, ma ci hè una Pruposta chì suggerisce l'aghjunghje sta opzione (https://dev.mysql.com/worklog/task/?id=1524).

PostgreSQL ùn sustene micca l'indici di bitmap, ma usa bitmaps simplici è operazioni di bit per cumminà i risultati di ricerca in parechji altri indici.

Tarantool hà indici di bitset è sustene e ricerche simplici nantu à elli.

Redis hà campi di bit simplici (https://redis.io/commands/bitfield) senza a capacità di circà per elli.

MongoDB ùn sustene ancu l'indici bitmap, ma ci hè ancu una Pruposta chì suggerisce chì sta opzione sia aghjuntu https://jira.mongodb.org/browse/SERVER-1723

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

Indici Bitmap in Go: ricerca à velocità salvatica

  • Ma un novu vicinu hè apparsu in casa nostra : Pilosa. Questa hè una nova basa di dati non-relazionale scritta in Go. Contene solu indici bitmap è basa tuttu nantu à elli. Ne parlemu un pocu dopu.

Implementazione in Go

Ma perchè l'indici bitmap sò cusì raramente utilizati? Prima di risponde à sta quistione, vogliu mustrà cumu implementà un indice bitmap assai simplice in Go.
Indici Bitmap in Go: ricerca à velocità salvatica
I bitmaps sò essenzialmente solu pezzi di dati. In Go, usemu fette di byte per questu.

Avemu un bitmap per una caratteristica di un ristorante, è ogni bit in u bitmap indica se un ristorante particulari hà sta pruprietà o micca.
Indici Bitmap in Go: ricerca à velocità salvatica
Avemu bisognu di duie funzioni d'aiutu. Unu serà utilizatu per riempie i nostri bitmaps cù dati casuali. Aleatoriu, ma cù una certa probabilità chì u ristorante hà ogni pruprietà. Per esempiu, crede chì ci sò assai pochi ristoranti in Mosca induve ùn pudete micca riservà una tavola, è mi pare chì circa 20% di i stabilimenti sò adattati per i vegetariani.

A seconda funzione cunvertisce u bitmap in una lista di ristoranti.
Indici Bitmap in Go: ricerca à velocità salvatica
Indici Bitmap in Go: ricerca à velocità salvatica
Per risponde à a dumanda "Mostrami ristoranti di prezzu chì anu un patio è ponu fà riservazioni", avemu bisognu di duie operazioni di bit: NOT è AND.

Pudemu simplificà u nostru codice un pocu usendu l'operatore più cumplessu AND NOT.

Avemu funzioni per ognuna di queste operazioni. I dui passanu per e fette, pigliate l'elementi currispundenti da ognunu, combina cù un pocu operazione è mette u risultatu in a fetta resultanti.
Indici Bitmap in Go: ricerca à velocità salvatica
È avà pudemu usà i nostri bitmaps è e funzioni per risponde à a ricerca di ricerca.
Indici Bitmap in Go: ricerca à velocità salvatica
U rendiment ùn hè micca cusì altu, ancu s'è e funzioni sò assai simplici è avemu salvatu assai soldi per ùn vultà micca una nova fetta resultanti ogni volta chì a funzione hè stata chjamata.

Dopu avè fattu un pocu di prufilu cù pprof, aghju nutatu chì u compilatore Go mancava una ottimisazione assai simplice ma assai impurtante: funzione inlining.
Indici Bitmap in Go: ricerca à velocità salvatica
U fattu hè chì u compilatore Go hè terribilmente paura di i loops chì passanu per fette, è categuricamente ricusa di funzioni inline chì cuntenenu tali loops.
Indici Bitmap in Go: ricerca à velocità salvatica
Ma ùn aghju micca paura è possu ingannà u compilatore usendu goto invece di un ciclu, cum'è in i boni vechji tempi.

Indici Bitmap in Go: ricerca à velocità salvatica
Indici Bitmap in Go: ricerca à velocità salvatica

E, cum'è pudete vede, avà u compilatore inlinerà felice a nostra funzione! In u risultatu, riescimu à salvà circa 2 microseconds. Micca male!

Indici Bitmap in Go: ricerca à velocità salvatica

U secondu collu di bottiglia hè faciule per vede s'ellu guardate attentamente à a pruduzzioni di l'assemblea. U compilatore hà aghjustatu un cuntrollu di e fruntiere di a fetta in u nostru ciclu più caldu. U fattu hè chì Go hè una lingua sicura, u compilatore hè a paura chì i mo trè argumenti (trè fette) sò di diverse dimensioni. Dopu tuttu, allora ci sarà una pussibilità teorica di l'occurrence di un cusì chjamatu buffer overflow.

Rassicuremu u compilatore dimustrendu chì tutte e fette sò a stessa dimensione. Pudemu fà questu aghjunghjendu un cuntrollu simplice à u principiu di a nostra funzione.
Indici Bitmap in Go: ricerca à velocità salvatica
Videndu questu, u compilatore salta felice a verificazione, è finisci per salvà un altru 500 nanosecondi.

Grandi butches

D'accordu, avemu riesciutu à strincà un pocu di prestazioni da a nostra implementazione simplice, ma questu risultatu hè in realtà assai peghju di ciò chì hè pussibule cù u hardware attuale.

Tuttu ciò chì facemu hè operazioni basi di bit, è i nostri prucessori li eseguinu assai efficace. Ma, sfurtunatamenti, avemu "alimentatu" u nostru processatore cù pezzi di travagliu assai chjuchi. E nostre funzioni facenu operazioni nantu à una basa byte per byte. Pudemu assai facilmente tweak u nostru codice per travaglià cù pezzi di 8 byte usendu fette UInt64.

Indici Bitmap in Go: ricerca à velocità salvatica

Comu si pò vede, stu picculu cambiamentu acceleratu u nostru prugramma ottu volte aumentendu a dimensione di batch da ottu volte. U guadagnu pò esse dettu lineare.

Indici Bitmap in Go: ricerca à velocità salvatica

Implementazione in assembler

Indici Bitmap in Go: ricerca à velocità salvatica
Ma questu ùn hè micca a fine. I nostri processori ponu travaglià cù pezzi di 16, 32 è ancu 64 bytes. Tali operazioni "larghe" sò chjamate istruzzioni unica dati multiplici (SIMD; una struzzione, assai dati), è u prucessu di trasfurmà u codice in modu chì usa tali operazioni hè chjamatu vectorization.

Sfortunatamente, u compilatore Go hè luntanu da eccellenti in a vectorizazione. Attualmente, l'unicu modu per vectorize u codice Go hè di piglià è mette queste operazioni manualmente usendu Go assembler.

Indici Bitmap in Go: ricerca à velocità salvatica

Go assembler hè una bestia strana. Probabilmente sapete chì a lingua di l'assemblea hè qualcosa chì hè assai ligata à l'architettura di l'urdinatore per quale scrive, ma ùn hè micca u casu in Go. Go assembler hè più cum'è un IRL (lingua di rappresentanza intermediata) o lingua intermediata: hè praticamente indipendente da a piattaforma. Rob Pike hà datu una prestazione eccellente rapportu annantu à questu tema parechji anni fà in GopherCon in Denver.

In più, Go usa un furmatu di u Pianu 9 inusual, chì difiere da i formati AT&T è Intel generalmente accettati.
Indici Bitmap in Go: ricerca à velocità salvatica
Hè sicuru di dì chì scrive Go assembler a manu ùn hè micca u più divertente.

Ma, per furtuna, ci sò digià dui arnesi d'altu livellu chì ci aiutanu à scrive Go assembler: PeachPy è avo. E duie utilità generanu Go assembler da codice di livellu più altu scrittu in Python è Go, rispettivamente.
Indici Bitmap in Go: ricerca à velocità salvatica
Queste utilità simplificà e cose cum'è l'allocazione di u registru, i cicli di scrittura, è in generale simplificanu u prucessu di entre in u mondu di a prugrammazione di assemblea in Go.

Avemu aduprà avo, cusì i nostri prugrammi seranu quasi regulare prugrammi Go.
Indici Bitmap in Go: ricerca à velocità salvatica
Questu hè l'esempiu più simplice di un prugramma avo. Avemu una funzione principale (), chì definisce in sè stessu a funzione Add () , u significatu di quale hè di aghjunghje dui numeri. Ci sò funzioni d'aiutu quì per uttene parametri per nome è uttene unu di i registri di processore gratuiti è adattati. Ogni operazione di processore hà una funzione currispondente nantu à avo, cum'è vistu in ADDQ. Infine, vedemu una funzione d'aiutu per almacenà u valore risultatu.
Indici Bitmap in Go: ricerca à velocità salvatica
Chjamendu go generate, eseguiremu u prugramma nantu à avo è in u risultatu, dui schedari seranu generati:

  • add.s cù u codice resultanti in Go assembler;
  • stub.go cù headers di funzione per cunnette i dui mondi: Go è assembler.

Indici Bitmap in Go: ricerca à velocità salvatica
Avà chì avemu vistu ciò chì avo faci è cumu, fighjemu e nostre funzioni. Aghju implementatu e versioni scalari è vettoriali (SIMD) di e funzioni.

Fighjemu prima e versioni scalari.
Indici Bitmap in Go: ricerca à velocità salvatica
Cum'è in l'esempiu precedente, dumandemu un registru di scopu generale gratuitu è ​​validu, ùn avemu micca bisognu di calculà offsets è dimensioni per l'argumenti. avo face tuttu questu per noi.
Indici Bitmap in Go: ricerca à velocità salvatica
Avemu usatu per aduprà etichette è goto (o salti) per migliurà u rendiment è ingannà u compilatore Go, ma avà u facemu da u principiu. U puntu hè chì i ciculi sò un cuncettu di livellu più altu. In assembler, avemu solu etichette è salti.
Indici Bitmap in Go: ricerca à velocità salvatica
U codice restante deve esse digià familiarizatu è capiscenu. Emulate un ciclu cù etichette è salti, pigliate un picculu pezzu di dati da i nostri dui fette, combina cù un pocu operazione (È NON in questu casu) è poi mette u risultatu in a fetta resultanti. Tuttu.
Indici Bitmap in Go: ricerca à velocità salvatica
Questu hè ciò chì u codice assembler finali pare. Ùn avemu micca bisognu di calculà l'offsets è e dimensioni (saltate in verde) o mantene a traccia di i registri utilizati (spuntati in rossu).
Indici Bitmap in Go: ricerca à velocità salvatica
Se paragunemu a prestazione di l'implementazione di a lingua assemblea cù a prestazione di a megliu implementazione in Go, videremu chì hè u listessu. È questu hè aspittatu. Dopu tuttu, ùn avemu micca fattu nunda di speciale - avemu solu riproduce ciò chì un compilatore Go faria.

Sfortunatamente, ùn pudemu micca furzà u compilatore à inline e nostre funzioni scritte in lingua assemblea. U compilatore Go attualmente ùn hà micca una tale funzione, ancu s'ellu ci hè stata una dumanda per aghjunghje per un bellu pezzu.

Hè per quessa hè impussibile di ottene alcun benefiziu da e piccule funzioni in lingua assemblea. Avemu bisognu di scrive grandi funzioni, o aduprà u novu pacchettu di matematica / bits, o bypassa a lingua assembler.

Fighjemu avà à e versioni vettoriali di e nostre funzioni.
Indici Bitmap in Go: ricerca à velocità salvatica
Per questu esempiu, aghju decisu d'utilizà AVX2, cusì avemu aduprà operazioni chì operanu nantu à pezzi di 32 byte. A struttura di u codice hè assai simili à a versione scalare: i paràmetri di carica, dumandendu un registru spartutu gratuitu, etc.
Indici Bitmap in Go: ricerca à velocità salvatica
Una innuvazione hè chì l'operazioni vettoriali più larghe utilizanu registri speziali largu. In u casu di 32-byte chunks, questi sò registri prefissati cù Y. Hè per quessa chì vede a funzione YMM () in u codice. Se aghju utilizatu AVX-512 cù pezzi di 64 bit, u prefissu seria Z.

A seconda innuvazione hè chì aghju decisu di utilizà una ottimisazione chjamata loop unrolling, chì significa fà ottu operazioni di loop manualmente prima di saltà à u principiu di u ciclu. Questa ottimisazione reduce u nùmeru di rami in u codice, è hè limitata da u numeru di registri gratuiti dispunibili.
Indici Bitmap in Go: ricerca à velocità salvatica
Ebbè, chì ne di u rendiment? Hè bella ! Avemu ottenutu una accelerazione di circa sette volte paragunatu à a megliu suluzione Go. Impressionante, nò?
Indici Bitmap in Go: ricerca à velocità salvatica
Ma ancu sta implementazione puderia esse potenzialmente accelerata usendu AVX-512, prefetching o un JIT (compilatore just-in-time) per u pianificatore di query. Ma questu hè certamente un tema per un rapportu separatu.

Prublemi cù l'indici bitmap

Avà chì avemu digià guardatu una implementazione simplice di un indice bitmap in Go è un assai più produtivu in lingua assemblea, parlemu infine perchè l'indici bitmap sò cusì raramente usati.
Indici Bitmap in Go: ricerca à velocità salvatica
I documenti più antichi citanu trè prublemi cù l'indici bitmap, ma i documenti più recenti è sustene chì ùn sò più pertinenti. Ùn ci immerghjemu micca in profondità in ognuna di sti prublemi, ma li guardemu superficialmente.

U prublema di alta cardinalità

Dunque, ci hè dettu chì l'indici bitmap sò adattati solu per i campi cù una cardinalità bassu, vale à dì quelli chì anu pochi valori (per esempiu, sessu o culore di l'ochji), è a ragiuni hè chì a rapprisintazioni abituale di tali campi (una bit per valore) in u casu di cardinalità alta, pigghiarà troppu spaziu è, in più, sti indici bitmap seranu pocu (raramente) pieni.
Indici Bitmap in Go: ricerca à velocità salvatica
Indici Bitmap in Go: ricerca à velocità salvatica
A volte pudemu usà una rapprisintazzioni sfarente, cum'è quella standard chì usemu per rapprisintà numeri. Ma era l'avventu di l'algoritmi di cumpressione chì hà cambiatu tuttu. In l'ultimi decennii, i scientisti è i circadori anu ghjuntu cun un gran numaru d'algoritmi di compressione per bitmaps. U so vantaghju principali hè chì ùn ci hè micca bisognu di decompressà i bitmaps per fà operazioni di bit - pudemu fà operazioni di bit direttamente nantu à bitmaps compressi.
Indici Bitmap in Go: ricerca à velocità salvatica
Ricertamenti, l'avvicinamenti hibridi anu cuminciatu à apparisce, cum'è i bitmaps ruganti. Adupranu simultaneamente trè rapprisintazioni diffirenti per i bitmaps - i bitmaps stessi, array è i cosiddetti bit runs - è equilibranu trà elli per maximizà u rendiment è minimizzà u cunsumu di memoria.

Pudete truvà bitmaps ruggiti in l'applicazioni più populari. Ci hè digià un gran numaru di implementazioni per una larga varietà di linguaggi di prugrammazione, cumprese più di trè implementazioni per Go.
Indici Bitmap in Go: ricerca à velocità salvatica
Un altru approcciu chì pò aiutà à trattà cun alta cardinalità hè chjamatu binning. Imagine chì avete un campu chì rapprisenta l'altezza di una persona. L'altezza hè un numeru in virgule flottante, ma noi l'omu ùn pensemu micca cusì. Per noi ùn ci hè micca differenza trà l'altitudine 185,2 cm è 185,3 cm.

Ci hè chì pudemu raggruppà valori simili in gruppi in 1 cm.

È s'ellu sapemu ancu chì assai pochi persone sò più brevi di 50 cm è più altu di 250 cm, allora pudemu essenzialmente turnà un campu cù cardinalità infinita in un campu cù una cardinalità di circa 200 valori.

Di sicuru, se necessariu, pudemu fà un filtru supplementu dopu.

Problema di larghezza di banda alta

U prublema dopu cù l'indici di bitmap hè chì l'aghjurnamentu pò esse assai caru.

E basa di dati devenu esse capace di aghjurnà e dati mentre potenzialmente centinaie di altre dumande cercanu e dati. Avemu bisognu di chjusi per evità prublemi cù l'accessu di dati cuncurrenti o altri prublemi di spartera. È induve ci hè una grande serratura, ci hè un prublema - cuntinzione di serratura, quandu sta serratura diventa un collu di buttiglia.
Indici Bitmap in Go: ricerca à velocità salvatica
Stu prublema pò esse risolta o aggirata usendu sharding o usendu indici versionati.

Sharding hè una cosa simplice è ben cunnisciuta. Pudete shard un indice bitmap cum'è qualsiasi altri dati. Invece di una grande serratura, uttene una mansa di picculi serrature è cusì sbarazzate di a cuntinzione di serratura.

A seconda manera di risolve u prublema hè di utilizà indici versionati. Pudete avè una copia di l'indici chì utilizate per a ricerca o a lettura, è una chì utilizate per scrive o aghjurnà. È una volta in un certu periudu di tempu (per esempiu, una volta ogni 100 ms o 500 ms) duplicate è scambià. Di sicuru, stu approcciu hè applicabile solu in i casi induve a vostra applicazione pò trattà un indice di ricerca ligeramente ritardatu.

Questi dui approcci ponu esse aduprati simultaneamente: pudete avè un indexu versionatu sharded.

E dumande più cumplesse

U prublema finali cù l'indici di bitmap hè chì ci hè dettu chì ùn sò micca bè adattati per i tipi più cumplessi di dumande, cum'è e dumande span.

Infatti, se pensate à questu, operazioni di bit cum'è AND, OR, etc. ùn sò micca assai adattati per e dumande à la "Mostrami alberghi cù tariffu di stanza da 200 à 300 dollari per notte".
Indici Bitmap in Go: ricerca à velocità salvatica
Una suluzione ingenua è assai imprudente seria di piglià i risultati per ogni valore di dollari è cunghjuntà cù una operazione OR bit à bit.
Indici Bitmap in Go: ricerca à velocità salvatica
Una suluzione ligeramente megliu seria di utilizà a raggruppamentu. Per esempiu, in gruppi di 50 dollars. Questu averebbe accelerà u nostru prucessu da 50 volte.

Ma u prublema hè ancu facilmente risolta cù una vista creata apposta per stu tipu di dumanda. In i documenti scientifichi hè chjamatu bitmaps codificati in intervalli.
Indici Bitmap in Go: ricerca à velocità salvatica
In questa rapprisintazioni, ùn avemu micca solu stabilitu un pocu per qualchì valore (per esempiu, 200), ma stabilisce stu valore è tuttu più altu. 200 è sopra. U stessu per 300: 300 è sopra. Eccetera.

Utilizendu sta rapprisintazioni, pudemu risponde à stu tipu di ricerca di ricerca attraversu l'indici solu duie volte. Prima, averemu una lista di l'alberghi induve a stanza costa menu o $ 300, è poi sguassemu da ellu quelli induve u costu di a stanza hè menu o $ 199. Pronti.
Indici Bitmap in Go: ricerca à velocità salvatica
Serete sorpresu, ma ancu i geoqueries sò pussibuli cù l'indici bitmap. U truccu hè di utilizà una rapprisintazioni geomètrica chì circundanu a vostra coordenada cù una figura geomètrica. Per esempiu, S2 da Google. A figura deve esse pussibule di rapprisintà in a forma di trè o più linii intersecting chì ponu esse numerati. In questu modu, pudemu turnà a nostra geoquery in parechje dumande "longu u gap" (longu di sti linee numerate).

Soluzioni pronte

Spergu chì vi hà interessatu un pocu è avà avete un altru strumentu utile in u vostru arsenale. Sè mai bisognu di fà qualcosa cusì, sapete chì manera di circà.

Tuttavia, micca tutti ùn anu u tempu, pacienza o risorse per creà indici bitmap da zero. In particulare quelli più avanzati, cù SIMD, per esempiu.

Per furtuna, ci sò parechje soluzioni pronti per aiutà.
Indici Bitmap in Go: ricerca à velocità salvatica

Bitmap ruggenti

Prima, ci hè quella stessa libreria di bitmaps ruggiti chì aghju digià parlatu. Contene tutti i cuntenituri necessarii è l'operazioni di bit chì avete bisognu di fà un indice bitmap cumpletu.
Indici Bitmap in Go: ricerca à velocità salvatica
Sfortunatamente, per u mumentu, nimu di l'implementazioni Go usa SIMD, chì significa chì l'implementazioni Go sò menu performanti cà l'implementazioni C, per esempiu.

Pilosa

Un altru pruduttu chì vi pò aiutà hè u DBMS Pilosa, chì, in fattu, hà solu indici bitmap. Questa hè una suluzione relativamente nova, ma hè vince i cori à grande velocità.
Indici Bitmap in Go: ricerca à velocità salvatica
Pilosa usa internu di bitmaps ruggiti è vi dà a capacità di usà, simplificà è spiegà tutte e cose ch'e aghju parlatu sopra: raggruppamenti, bitmaps codificati in gamma, u cuncettu di un campu, etc.

Fighjemu rapidamente un esempiu di utilizà Pilosa per risponde à una quistione chì site digià familiarizata.
Indici Bitmap in Go: ricerca à velocità salvatica
L'esempiu hè assai simili à ciò chì avete vistu prima. Creemu un cliente à u servitore Pilosa, creanu un indexu è i campi necessarii, poi riempie i nostri campi cù dati aleatorii cù probabilità è, infine, eseguite a query familiar.

Dopu à quessa, avemu usatu NOT nant'à u campu "caru", dopu intersece u risultatu (o AND it) cù u campu "terrazza" è cù u campu "riservazioni". È infine, avemu u risultatu finali.
Indici Bitmap in Go: ricerca à velocità salvatica
Spergu veramente chì in u futuru prevedibile stu novu tipu d'indici appariscerà ancu in DBMS cum'è MySQL è PostgreSQL - indici bitmap.
Indici Bitmap in Go: ricerca à velocità salvatica

cunchiusioni

Indici Bitmap in Go: ricerca à velocità salvatica
Sì ùn avete micca addormentatu ancu, grazie. Aviu avutu toccu brevemente parechji temi per via di u tempu limitatu, ma spergu chì a conversazione hè stata utile è forse ancu motivante.

L'indici Bitmap sò bè ​​​​per sapè, ancu s'ellu ùn ne avete micca bisognu avà. Ch'elli esse un altru strumentu in u vostru arnesi.

Avemu guardatu diversi trucchi di prestazione per Go è cose chì u compilatore Go ùn gestisce ancu bè. Ma questu hè assolutamente utile per ogni programatore Go per sapè.

Hè tuttu ciò chì vulia dì vi. Grazie!

Source: www.habr.com

Add a comment