
Nonostante ci siano molte informazioni disponibili quasi ovunque, i database analitici sono ancora abbastanza esotici. Sono poco conosciuti e ancora meno saputi utilizzare in modo efficace. Molti continuano a "mangiare il cactus" con MySQL o PostgreSQL, progettati per altri scenari, a lottare con NoSQL o a pagare troppo per soluzioni commerciali. ClickHouse cambia le regole del gioco e riduce significativamente la soglia di ingresso nel mondo dei DBMS analitici.
Presentazione al BackEnd Conf 2018 e pubblicata con il permesso del relatore.


Chi sono e perché parlo di ClickHouse? Sono il direttore dello sviluppo di LifeStreet, che utilizza ClickHouse. Inoltre, sono il fondatore di Altinity. Questo è un partner di Yandex, che promuove ClickHouse e aiuta Yandex a rendere ClickHouse più prospere. Sono anche pronto a condividere conoscenze su ClickHouse.

E non sono il fratello di Petya Zaytsev. Me lo chiedono spesso. No, non siamo fratelli.

«È risaputo» che ClickHouse:
- È molto veloce,
- È molto comodo,
- È usato in Yandex.
È un po' meno noto in quali aziende e come viene utilizzato.

Vi parlerò di cosa, dove e come viene utilizzato ClickHouse, oltre a Yandex.
Parlerò di come compiti specifici vengono risolti utilizzando ClickHouse in diverse aziende, quali strumenti ClickHouse potete utilizzare per i vostri compiti e come sono stati utilizzati in diverse aziende.
Ho selezionato tre esempi che mostrano ClickHouse da angolazioni diverse. Penso che sarà interessante.

La prima domanda: «A cosa serve ClickHouse?». Sembra una domanda piuttosto ovvia, ma ci sono più risposte di una sola.

- La prima risposta è per le prestazioni. ClickHouse è molto veloce. L'analisi su ClickHouse è anche molto rapida. Spesso può essere utilizzato dove qualcos'altro funziona molto lentamente o in modo molto scarso.
- La seconda risposta è il costo. E prima di tutto il costo della scalabilità. Ad esempio, Vertica è un database completamente diverso. Funziona molto bene se non avete molte terabyte di dati. Ma quando si parla di centinaia di terabyte o petabyte, il costo della licenza e del supporto diventa una somma piuttosto sostanziosa. E questo è costoso. Mentre ClickHouse è gratuito.
- La terza risposta è il costo operativo. Questo è un approccio un po' diverso. RedShift è un ottimo analogo. Su RedShift puoi implementare una soluzione molto rapidamente. Funzionerà bene, ma ogni ora, ogni giorno e ogni mese dovrai pagare abbastanza caro Amazon, perché è un servizio realmente costoso. Anche Google BigQuery lo è. Chiunque lo abbia utilizzato sa che puoi eseguire diverse query e ricevere all'improvviso una fattura di centinaia di dollari.
In ClickHouse non ci sono questi problemi.

Dove viene attualmente utilizzato ClickHouse? Oltre a Yandex, ClickHouse è usato in un sacco di aziende e attività diverse.
- Prima di tutto, si tratta di analisi delle web app, cioè è un caso d'uso venuto da Yandex.
- Molte aziende AdTech utilizzano ClickHouse.
- Numerose aziende che hanno bisogno di analizzare i log operativi da diverse fonti.
- Alcune aziende utilizzano ClickHouse per monitorare i log di sicurezza. Li caricano in ClickHouse, generano report e ottengono i risultati di cui hanno bisogno.
- Le aziende iniziano a utilizzarlo per analisi finanziaria, cioè gradualmente anche le grandi aziende si avvicinano a ClickHouse.
- CloudFlare. Chiunque segua ClickHouse avrà sicuramente sentito il nome di questa azienda. È uno dei principali contributori della community. Hanno anche un'installazione di ClickHouse molto seria. Ad esempio, hanno creato un Kafka Engine per ClickHouse.
- Le aziende di telecomunicazioni hanno iniziato ad usarlo. Diverse aziende utilizzano ClickHouse sia come prova di concetto che già in produzione.
- Un'azienda utilizza ClickHouse per monitorare i processi produttivi. Testano i chip, annotano un sacco di parametri, circa 2.000 caratteristiche. E poi analizzano se il lotto è buono o cattivo.
- Analisi della blockchain. C'è un'azienda russa chiamata Bloxy.info. Si occupano dell'analisi della rete ethereum. Anche questo l'hanno realizzato su ClickHouse.

Tra l'altro, le dimensioni non contano. Ci sono molte aziende che utilizzano un piccolo server. E questo permette di risolvere i loro problemi. E ancora più aziende utilizzano grandi cluster di molti server o decine di server.
E se guardiamo ai record, allora:
- Yandex: oltre 500 server, 25 miliardi di record al giorno che salvano lì.
- LifeStreet: 60 server, circa 75 miliardi di record al giorno. Meno server, più record rispetto a Yandex.
- CloudFlare: 36 server, 200 miliardi di record al giorno che conservano. Hanno ancora meno server e molti più dati che conservano.
- Bloomberg: 102 server, circa un trilione di record al giorno. Leader nel numero di record.

Geograficamente, questo è molto. Questa mappa mostra la heatmap, dove ClickHouse è utilizzato nel mondo. Qui si evidenziano Russia, Cina, America. Ci sono poche nazioni europee. Si possono identificare 4 cluster.
Questo è un'analisi comparativa, qui non è necessario cercare cifre assolute. È un'analisi dei visitatori che leggono materiale in inglese sul sito di Altinity, poiché non ci sono materiali in russo. E Russia, Ucraina, Bielorussia, cioè la parte russofona della comunità, è la più numerosa. Seguono gli USA e il Canada. La Cina sta recuperando molto rapidamente. Sei mesi fa la Cina era quasi inesistente, ora ha già superato l'Europa e continua a crescere. Anche la vecchia Europa non rimane indietro, e, sorprendentemente, il leader nell'uso di ClickHouse è la Francia.

Perché sto raccontando tutto questo? Per mostrare che ClickHouse sta diventando la soluzione standard per l'analisi dei Big Data ed è già ampiamente utilizzato. Se lo usi, sei nel giusto trend. Se non lo stai ancora usando, non temere di rimanere solo e di non avere aiuto, perché già molte persone lo stanno facendo.

Questi sono esempi di utilizzo reale di ClickHouse in diverse aziende.
- Il primo esempio è una rete pubblicitaria: migrazione da Vertica a ClickHouse. Conosco diverse aziende che sono passate a ClickHouse da Vertica o sono in fase di transizione.
- Il secondo esempio è un magazzino transazionale su ClickHouse. Questo esempio è costruito su antipattern. Tutto ciò che non si dovrebbe fare in ClickHouse secondo i consigli degli sviluppatori è stato fatto qui. E, tuttavia, è stato fatto in modo così efficace che funziona. E funziona molto meglio di una tipica soluzione transazionale.
- Il terzo esempio è il calcolo distribuito su ClickHouse. C'era una domanda su come integrare ClickHouse nell'ecosistema Hadoop. Mostrerò un esempio di come un'azienda ha realizzato su ClickHouse qualcosa di simile a un contenitore di map reduce, prestando attenzione alla localizzazione dei dati, ecc., per risolvere un compito molto non banale.

- LifeStreet – È una azienda nel settore Ad Tech che ha tutte le tecnologie associate a una rete pubblicitaria.
- Si occupa di ottimizzazione degli annunci, programmatic bidding.
- Molti dati: circa 10 miliardi di eventi al giorno. Inoltre, gli eventi possono dividersi in più sotto-eventi.
- Molti clienti per questi dati, e non sono solo persone; ci sono molti di più: sono vari algoritmi che si occupano dell'offerta programmatica.

L'azienda ha percorso un lungo e difficile cammino. Ne ho parlato a HighLoad. Inizialmente, LifeStreet è passata da MySQL (con una breve sosta su Oracle) a Vertica. È possibile trovare racconti al riguardo.
Tutto andava molto bene, ma è diventato chiaro abbastanza rapidamente che i dati crescevano e Vertica era costoso. Quindi si cercavano varie alternative. Alcune di esse sono elencate qui. In effetti, abbiamo realizzato un proof of concept o test di performance per quasi tutti i database che erano disponibili sul mercato dal 2013 al 2016 e che erano abbastanza adeguati in termini di funzionalità. Di parte di essi ho anche parlato a HighLoad.

La sfida era migrare da Vertica in primo luogo, perché i dati crescevano. E sono cresciuti esponenzialmente per diversi anni. Poi sono stati stabili, ma comunque. Prevedendo questa crescita e la richiesta aziendale relativa al volume dei dati per l'analisi, era chiaro che presto si sarebbe parlato di petabyte. E pagare per i petabyte è già molto costoso, quindi si cercava un'alternativa alla quale migrare.

Dove migrare? A lungo non è stato chiaro dove andare, perché da un lato ci sono database commerciali, che sembrano funzionare piuttosto bene. Alcuni funzionano quasi altrettanto bene come Vertica, altri peggio. Ma sono tutti costosi; non si riusciva a trovare nulla di migliore e più economico.
Dall'altro lato, ci sono soluzioni open source, non tante, cioè per l'analisi si possono contare sulle dita. E sono gratuite o economiche, ma funzionano lentamente. E spesso mancano della funzionalità necessaria e utile.
E nulla riusciva a combinare il meglio delle basi di dati commerciali e tutto ciò che è disponibile gratuitamente nel mondo open source.

Nulla finché, inaspettatamente, Yandex non ha tirato fuori ClickHouse, come un coniglio da un cappello da prestigiatore. È stata una soluzione inaspettata, ancora oggi si pongono domande: «Perché?», ma tuttavia.

E subito nell'estate del 2016 abbiamo iniziato a guardare cosa fosse ClickHouse. E si è scoperto che a volte può essere più veloce di Vertica. Abbiamo testato diversi scenari su varie query. E se la query utilizzava solo una tabella, ossia senza alcun join, ClickHouse era due volte più veloce di Vertica.
Non mi sono risparmiato e ho controllato ulteriori test di Yandex nei giorni scorsi. Lì è lo stesso: ClickHouse è due volte più veloce di Vertica, quindi ne parlano spesso.
Ma se nelle query ci sono join, le cose non sono molto chiare. E ClickHouse può essere due volte più lento di Vertica. Se si modifica leggermente la query e la si riscrive, allora sono più o meno uguali. Non male. E gratuito.

E ottenuti i risultati dei test, e guardando da diverse angolazioni, LifeStreet è passato a ClickHouse.

Ricordo che siamo nel 2016. Era come nella barzelletta sui topi, che piangevano e si pungevano, ma continuavano a mangiare il cactus. Ne hanno parlato in dettaglio, ci sono video al riguardo, ecc.

Non entrerò nei dettagli, parlerò solo dei risultati e di alcune cose interessanti che non ho menzionato allora.
I risultati sono questi:
- Migrazione riuscita e il sistema funziona già in produzione da oltre un anno.
- Le prestazioni e la flessibilità sono aumentate. Da 10 miliardi di record che potevamo permetterci di mantenere per un giorno e per poco tempo, ora LifeStreet conserva 75 miliardi di record al giorno e può farlo per 3 mesi o più. Se calcoliamo ai picchi, si salvano fino a un milione di eventi al secondo. Più di un milione di query SQL al giorno arrivano a questo sistema, principalmente da vari bot.
- Nonostante per ClickHouse siano stati utilizzati più server rispetto a Vertica, c'è stato un risparmio anche sull'hardware, poiché in Vertica venivano utilizzati dischi SAS piuttosto costosi. In ClickHouse sono stati usati dischi SATA. E perché? Perché in Vertica l'inserimento è sincronizzato. E la sincronizzazione richiede che i dischi non rallentino troppo, così come che la rete non rallenti troppo, ossia è un'operazione piuttosto costosa. In ClickHouse l'inserimento è asincrono. Inoltre, si può sempre scrivere in locale, senza costi aggiuntivi per questo, quindi i dati in ClickHouse possono essere inseriti molto più velocemente che in Vertica anche su dischi non tra i più veloci. E per la lettura è più o meno lo stesso. La lettura su SATA, se sono in RAID, è sufficientemente veloce.
- Non limitato dalla licenza, ovvero 3 petabyte di dati su 60 server (20 server sono una replica) e 6 trilioni di record in fatti e aggregati. Nulla di simile poteva permettersi con Vertica.

Ora passo alle questioni pratiche in questo esempio.
- Primo: è uno schema efficiente. Dallo schema dipende molto.
- Secondo: è la generazione di SQL efficiente.

Una tipica query OLAP è un select. Parte delle colonne va in group by, parte delle colonne va in funzioni aggregate. C'è un where, che può essere visto come un'istantanea del cubo. L'intero group by può essere considerato una proiezione. E per questo si chiama analisi multidimensionale dei dati.

E spesso viene modellato come uno schema a stella, con un fatto centrale e le sue caratteristiche ai lati, ai raggi.

E dal punto di vista del design fisico, di come questo si dispone sulle tabelle, di solito si fa una rappresentazione normalizzata. Puoi denormalizzare, ma è costosa in termini di spazio su disco e non molto efficiente per le query. Pertanto, di solito si fa una rappresentazione normalizzata, ovvero una tabella dei fatti e molte, molte tabelle di dimensioni.
Ma in ClickHouse questo funziona male. Ci sono due motivi:
- Il primo è che in ClickHouse non ci sono un buon supporto per i join, ovvero i join ci sono, ma sono scadenti. Attualmente scadenti.
- Il secondo è che le tabelle non si aggiornano. Di solito in queste tabelle, che circondano lo schema a stella, c'è bisogno di cambiare qualcosa. Ad esempio, il nome del cliente, il nome dell'azienda e altro. E questo non funziona.
E ci sono soluzioni a questo in ClickHouse. Anzi, ce ne sono due:
- La prima è l'uso dei dizionari. I Dizionari Esterni aiutano a risolvere il 99% del problema con lo schema a stella, con gli aggiornamenti e altro.
- La seconda è l'uso degli array. Gli array aiutano anche a eliminare i join e i problemi di normalizzazione.

- Non è necessario un join.
- Aggiornabili. Da marzo 2018 è stata introdotta una possibilità non documentata (che non troverai nella documentazione) di aggiornare i dizionari parzialmente, cioè solo quei record che sono cambiati. Praticamente è come una tabella.
- Sempre in memoria, quindi i join con il dizionario funzionano più velocemente rispetto a una tabella che è sul disco e non è nemmeno certo che sia nella cache, molto probabilmente no.

- Nemmeno un join è necessario.
- Questa è una rappresentazione compatta 1 a molti.
- E a mio avviso, gli array sono fatti per i nerd. Sono funzioni lambda e altro.
Non è solo una frase ad effetto. È una funzionalità molto potente che consente di fare molte cose in modo semplice ed elegante.

Esempi tipici che aiutano a gestire gli array. Questi esempi sono semplici e abbastanza esplicativi:
- Ricerca per tag. Se hai hashtag e desideri trovare alcune registrazioni per un hashtag.
- Ricerca per coppie chiave-valore. Ci sono anche alcuni attributi con un valore.
- Memorizzazione di elenchi di chiavi che devi convertire in qualcos'altro.
Tutte queste attività possono essere svolte senza array. I tag possono essere messi in una riga e selezionati con un'espressione regolare o in una tabella separata, ma in tal caso dovrai fare join.

In ClickHouse non è necessario fare nulla, basta descrivere un array di stringhe per gli hashtag o creare una struttura annidata per sistemi di tipo chiave-valore.
La struttura annidata potrebbe non essere il termine più accurato. Si tratta di due array che hanno una parte comune nel nome e alcune caratteristiche correlate.
E cercare per tag è molto semplice. Esiste una funzione has, che verifica se un elemento è presente nell'array. Ecco, abbiamo trovato tutte le registrazioni relative alla nostra conferenza.
La ricerca per subid è un po' più complessa. Prima dobbiamo trovare l'indice della chiave, poi prendere l'elemento con quell'indice e controllare se il valore è quello che ci serve. Eppure, è molto semplice e compatto.
L'espressione regolare che vorresti scrivere, se tutto ciò fosse memorizzato in una sola riga, sarebbe, per prima cosa, molto goffa. E, per seconda, funzionerebbe molto più a lungo rispetto a due array.

Un altro esempio. Hai un array in cui memorizzi gli ID. E puoi convertirli in nomi. La funzione arrayMap. È una tipica funzione lambda. Le espressioni lambda vengono passate. E per ogni ID del dizionario estrae il valore del nome.
Allo stesso modo si può fare anche la ricerca. Viene passata una funzione predicato che verifica a cosa corrispondono gli elementi.

Queste funzionalità semplificano notevolmente lo schema e risolvono molte problematiche.
Ma il problema successivo, con cui ci siamo confrontati e di cui vorrei parlare, sono le query efficienti.
- In ClickHouse non c'è un pianificatore di query. Non esiste affatto.
- Tuttavia, è necessario pianificare comunque query complesse. In quali casi?
- Se nella query ci sono più join che stai annidando in sottoquery. E l'ordine in cui vengono eseguiti è importante.
- E in secondo luogo, se la query è distribuita. Perché in una query distribuita solo la sottoquery più interna viene eseguita in modo distribuito, mentre tutto il resto viene passato a un singolo server a cui ti sei connesso e viene eseguito lì. Quindi, se hai query distribuite con molti join, devi selezionare l'ordine.
E anche nei casi più semplici a volte è opportuno fare il lavoro del pianificatore e riscrivere un po' le query.

Ecco un esempio. A sinistra c'è la query che mostra le prime 5 nazioni. E impiega 2,5 secondi, secondo me. A destra c'è la stessa query, ma leggermente riscritta. Invece di raggruppare per stringa, abbiamo iniziato a raggruppare per chiave (int). E questo è più veloce. Poi abbiamo collegato il dizionario al risultato. Invece di 2,5 secondi, la query impiega 1,5 secondi. Questo è buono.

Un esempio simile riguarda la riscrittura dei filtri. Qui c'è una query sulla Russia. Impiega 5 secondi. Se la riscriviamo in modo da confrontare di nuovo non stringhe, ma numeri con un certo insieme di chiavi che riguardano la Russia, sarà molto più veloce.

Ci sono molti trucchi del genere. E permettono di accelerare notevolmente le query che sembra già funzionino rapidamente, o al contrario, funzionino lentamente. Possono essere rese ancora più veloci.

- Massima lavorazione in modalità distribuita.
- Ordinamento per tipologia minima, come ho fatto con gli interi.
- Se ci sono dei join, dizionari, è meglio farli come ultima cosa, quando hai già i dati almeno parzialmente raggruppati, così l'operazione di join o la chiamata al dizionario sarà invocata meno volte e sarà più veloce.
- Sostituzione dei filtri.
Ci sono anche altre tecniche, non solo quelle che ho dimostrato. E tutte queste consentono di accelerare a volte in modo significativo l'esecuzione delle query.

Passiamo al prossimo esempio. L'azienda X dagli Stati Uniti. Cosa fa?
C'era un compito:
- Collegamento offline delle transazioni pubblicitarie.
- Modellazione di diversi modelli di collegamento.

Qual è lo scenario?
Un visitatore normale entra nel sito, ad esempio, 20 volte al mese da diversi annunci o semplicemente arriva occasionalmente senza alcun annuncio, perché ricorda questo sito. Osserva alcuni prodotti, li mette nel carrello, li toglie dal carrello. E, alla fine, acquista qualcosa.
Domande ragionevoli: "A chi bisogna pagare per la pubblicità, se necessario?" e "Quale pubblicità lo ha influenzato, se lo ha fatto?". Ossia, perché ha acquistato e come fare in modo che persone simili a lui acquistino anch'esse?
Per risolvere questo compito, è necessario collegare correttamente gli eventi che si verificano sul sito web, ossia costruire un legame tra di essi. Poi è necessario inviarli per analisi in DWH. E sulla base di questa analisi costruire modelli su chi e quale pubblicità mostrare.

Una transazione pubblicitaria è un insieme di eventi collegati dell'utente, che inizia con la visualizzazione di un annuncio, poi accade qualcosa, e successivamente potrebbe esserci un acquisto, e poi ci potrebbero essere acquisti all'interno dell'acquisto. Ad esempio, se si tratta di un'app mobile o di un gioco mobile, di solito l'installazione dell'app è gratuita, mentre se si fa qualcosa in più, potrebbero essere richiesti dei soldi. E più una persona spende nell'app, più è preziosa. Ma per questo è necessario collegare tutto.

Ci sono molti modelli di collegamento.
I più popolari sono:
- Last Interaction, dove interaction può essere un clic o una visualizzazione.
- First Interaction, ossia la prima cosa che ha portato l'utente sul sito.
- Combinazione lineare – a tutti lo stesso valore.
- Diminuzione.
- E altro ancora.

E come ha funzionato tutto questo originariamente? C'era Runtime e Cassandra. Cassandra veniva utilizzata come archivio delle transazioni, ossia conteneva tutte le transazioni correlate. E quando arrivava un certo evento in Runtime, ad esempio, la visualizzazione di una certa pagina o altro, si faceva una richiesta a Cassandra – c'è questa persona o no. Poi si estraevano le transazioni che le appartenevano. E si effettuava il collegamento.
E se si aveva fortuna, e nella richiesta c'era un transaction id, era facile. Ma di solito non si ha fortuna. Pertanto, era necessario trovare l'ultima transazione o la transazione con l'ultimo clic e così via.
E questo funzionava molto bene, fino a quando il collegamento era legato all'ultimo clic. Perché ci sono, diciamo, 10 milioni di clic al giorno, 300 milioni al mese, se si imposta una finestra di un mese. E poiché in Cassandra tutto questo deve essere in memoria affinché funzioni rapidamente, dato che richiede a Runtime di rispondere velocemente, servivano circa 10-15 server.
Ma quando si è voluto collegare la transazione alla visualizzazione, è diventato subito meno divertente. E perché? È evidente che servono 30 volte più eventi da memorizzare. E quindi ci vogliono 30 volte più server. E risulta che è una cifra astronomica. Mantenere fino a 500 server per fare il collegamento, mentre in Runtime ci sono significativamente meno server, è una cifra non corretta. E hanno iniziato a pensare a cosa fare.

E sono arrivati a ClickHouse. Ma come farlo su ClickHouse? A prima vista sembra un insieme di antipattern.
- La transazione cresce, noi le attacchiamo eventi sempre nuovi, cioè è mutabile, ed ClickHouse non lavora molto bene con oggetti mutabili.
- Quando un visitatore arriva, dobbiamo estrarre le sue transazioni per chiave, per il suo visit id. Anche questa è una query punto, e in ClickHouse non si fa così. Di solito in ClickHouse ci sono grandi... scansioni, ma qui dobbiamo recuperare alcune registrazioni. Anche questo è un antipattern.
- Inoltre, la transazione era in json, ma non volevano riscriverla, quindi volevano memorizzare json in modo non strutturato, e se necessario, estrarre qualcosa da esso. E questo è anche un antipattern.
Cioè, un insieme di antipattern.

Tuttavia, siamo riusciti a fare un sistema che ha funzionato molto bene.
Cosa è stato fatto? È stato introdotto ClickHouse, nel quale venivano caricati i log, suddivisi in registrazioni. È emerso un servizio attribuito, che riceveva i log da ClickHouse. Successivamente, per ogni registrazione, per visit id, si ottenevano le transazioni che potevano essere ancora non elaborate, più gli snapshot, cioè transazioni già collegate, ovvero il risultato del lavoro precedente. Da esse si elaborava già la logica, si selezionava la transazione corretta, si collegavano nuovi eventi. Si registrava di nuovo nel log. Il log tornava in ClickHouse, cioè è un sistema ciclico costante. Inoltre, andava in DWH per essere analizzato.
In questo modo non funzionava molto bene. E per facilitare le cose a ClickHouse, quando si effettuava una richiesta per visit id, raggruppavamo queste richieste in blocchi da 1.000 a 2.000 visit id e estraevamo per 1.000-2.000 persone tutte le transazioni. E così tutto ha cominciato a funzionare.

Se si guarda all'interno di ClickHouse, ci sono solo 3 tabelle principali che si occupano di tutto ciò.
La prima tabella in cui vengono caricati i log, i quali vengono caricati praticamente senza elaborazione.
La seconda tabella. Attraverso una materialized view, venivano estratti dai log gli eventi non ancora attribuiti, cioè non correlati. E attraverso la materialized view venivano estratte le transazioni per costruire uno snapshot. Cioè, una materiale view speciale costruiva lo snapshot, ovvero l'ultima stato accumulato della transazione.

Qui è scritto un testo in SQL. Vorrei commentare alcune cose importanti in esso.
La prima cosa importante è la possibilità in ClickHouse di estrarre colonne da json, campi. Cioè, in ClickHouse ci sono alcuni metodi per lavorare con json. Sono molto, molto primitivi.
visitParamExtractInt permette di estrarre attributi da json, cioè il primo colpo funziona. E in questo modo è possibile estrarre il transaction id o il visit id. Questo è uno.
Il secondo è che qui è stato utilizzato un campo materialized astuto. Cosa significa? Significa che non puoi inserirlo nella tabella, cioè non viene inserito, viene calcolato e memorizzato durante l'inserimento. Durante l'inserimento, ClickHouse fa il lavoro per te. E viene già estratto da json ciò di cui avrai bisogno in seguito.
In questo caso la materialized view è per le righe non elaborate. E si utilizza proprio la prima tabella con log praticamente grezzi. E cosa fa? Innanzitutto, cambia l'ordinamento, cioè ora l'ordinamento avviene per visit id, perché abbiamo bisogno di estrarre rapidamente la transazione di una specifica persona.
La seconda cosa importante è index_granularity. Se hai visto MergeTree, di solito per default index_granularity è impostato su 8.192. Cosa significa? È un parametro di rarità dell'indice. In ClickHouse l'indice è raro, non indicizza mai ogni singolo record. Lo fa ogni 8.192. Ed è positivo quando è necessario calcolare molti dati, ma negativo quando ce ne sono pochi, perché c'è un grande overhead. E se si riduce la granularità dell'indice, si riduce l'overhead. Non si può ridurre a uno, perché potrebbe non esserci abbastanza memoria. L'indice è sempre memorizzato in memoria.

E lo snapshot utilizza alcune funzioni interessanti di ClickHouse.
In primo luogo, c'è l'AggregatingMergeTree. E in AggregatingMergeTree viene memorizzato l'argMax, cioè quello è lo stato della transazione corrispondente all'ultimo timestamp. Le transazioni vengono continuamente generate per questo visitatore. E nello stato più recente di questa transazione abbiamo aggiunto un evento e abbiamo ottenuto un nuovo stato. È tornato in ClickHouse. E attraverso l'argMax in questa vista materializzata possiamo sempre ottenere lo stato attuale.

- Il legame è 'slegato' dal Runtime.
- Vengono memorizzati e elaborati fino a 3 miliardi di transazioni al mese. È un ordine di grandezza superiore rispetto a quanto si aveva in Cassandra, cioè in un sistema transazionale tipico.
- Cluster di 2x5 server ClickHouse. 5 server e ogni server ha una replica. È anche meno di quanto fosse in Cassandra per fare attribuzione basata su clic, mentre qui abbiamo quella basata su impression. Cioè, invece di aumentare il numero di server di 30 volte, siamo riusciti a ridurlo.

E l'ultimo esempio è una compagnia finanziaria Y, che analizzava le correlazioni delle variazioni dei prezzi delle azioni.
E l'obiettivo era questo:
- Ci sono circa 5.000 azioni.
- I prezzi sono noti ogni 100 millisecondi.
- I dati si sono accumulati per 10 anni. Evidentemente, per alcune aziende un po' di più, per altre un po' di meno.
- In totale circa 100 miliardi di righe.
E dovevamo calcolare la correlazione delle variazioni.

Ci sono due azioni e i loro prezzi. Se una sale, e l'altra sale, allora questa è una correlazione positiva, cioè una cresce e l'altra cresce. Se una sale, come alla fine del grafico, mentre l'altra scende, allora questa è una correlazione negativa, cioè quando una cresce, l'altra scende.
Analizzando queste variazioni reciproche è possibile fare previsioni sul mercato finanziario.

Ma il compito è complesso. Cosa viene fatto per questo? Abbiamo 100 miliardi di registrazioni, che contengono: tempo, azione e prezzo. Dobbiamo prima calcolare 100 miliardi di volte il runningDifference dell'algoritmo del prezzo. Il runningDifference è una funzione in ClickHouse che calcola la differenza tra due righe consecutivamente.
E dopo questo, dobbiamo calcolare la correlazione, anzi, la correlazione deve essere calcolata per ogni coppia. Per 5.000 azioni ci sono 12,5 milioni di coppie. E questo è molto, cioè 12,5 volte bisogna calcolare una funzione di correlazione del genere.
E se qualcuno ha dimenticato, x e y rappresentano il valore atteso del campione. Cioè, non è sufficiente calcolare solo le radici e le somme, ma bisogna anche calcolare altre somme all'interno di queste somme. Devono essere eseguiti un sacco di calcoli 12,5 milioni di volte e bisogna anche raggrupparli per ore. E le ore non sono poi così poche. E bisogna farlo in 60 secondi. È uno scherzo.

Bisognava farlo in qualche modo, perché tutto funzionava molto, molto lentamente, prima che arrivasse ClickHouse.

Hanno provato a calcolare questo su Hadoop, su Spark, su Greenplum. E tutto era molto lento o costoso. Cioè, era possibile calcolare in qualche modo, ma poi costava caro.

Poi è arrivato ClickHouse e tutto è migliorato notevolmente.
Ricordo che abbiamo un problema di localizzazione dei dati, quindi le correlazioni non possono essere localizzate. Non possiamo mettere parte dei dati su un server, parte su un altro e calcolare; dobbiamo avere tutti i dati ovunque.
Cosa hanno fatto? I dati erano inizialmente localizzati. Su ciascun server vengono memorizzati i dati di pricing di un determinato set di azioni. E non si sovrappongono. Pertanto, è possibile calcolare il logReturn in modo parallelo e indipendente, tutto avviene mentre è parallelo e distribuito.
Successivamente, hanno deciso di ridurre questi dati senza perderne l'espressività. Ridurre usando array, cioè per ciascun intervallo di tempo creare un array delle azioni e un array dei prezzi. In questo modo i dati occupano molto meno spazio. E sono un po' più facili da gestire. Queste sono operazioni quasi parallele, cioè calcoliamo parzialmente in modo parallelo e poi registriamo sul server.
Dopo di ciò, questi dati possono essere replicati. La lettera "r" indica che questi dati sono stati replicati. Cioè, abbiamo gli stessi dati su tutti e tre i server – questi array.
E con uno script speciale, da questo insieme di 12,5 milioni di correlazioni che devono essere calcolate, è possibile creare pacchetti. Cioè, 2.500 compiti da 5.000 coppie di correlazioni. E questi compiti possono essere calcolati su un particolare server ClickHouse. Ha tutti i dati, perché i dati sono uguali e può calcolarli in sequenza.

Ancora una volta, ecco come si presenta. Innanzitutto, abbiamo tutti i dati in questa struttura: tempo, azioni, prezzo. Poi abbiamo calcolato il logReturn, cioè i dati nella stessa struttura, solo che invece del prezzo abbiamo già il logReturn. Successivamente li abbiamo rielaborati, quindi abbiamo ottenuto tempo e groupArray per le azioni e per i prezzi. Abbiamo unito i dati. E dopo abbiamo generato una moltitudine di task e li abbiamo alimentati a ClickHouse affinché li elaborasse. E funziona.

Nel proof of concept, il task era un sotto-task, cioè con dati ridotti. E solo su tre server.
Questi primi due passaggi: il calcolo del Log_return e l'incapsulamento in array hanno impiegato circa un'ora ciascuno.
Il calcolo della correlazione ha richiesto circa 50 ore. Ma 50 ore sono poche, perché in passato ci volevano settimane. È stato un grande successo. E se consideriamo, a 70 volte al secondo, tutto veniva elaborato su questo cluster.
Ma la cosa più importante è che questo sistema è praticamente privo di colli di bottiglia, cioè scala praticamente in modo lineare. E questo è stato verificato. È stato scalato con successo.

- Uno schema corretto è metà del successo. E uno schema corretto prevede l'utilizzo di tutte le tecnologie necessarie di ClickHouse.
- Summing/AggregatingMergeTrees sono tecnologie che consentono di aggregare o calcolare lo stato dello snapshot come caso particolare. E questo semplifica notevolmente molte cose.
- Le Materialized Views permettono di aggirare il vincolo di un solo indice. Forse non l'ho spiegato molto chiaramente, ma quando caricavamo i log, i log grezzi erano in una tabella con un solo indice, mentre sui log degli attribute erano in un'altra tabella, cioè gli stessi dati, solo filtrati, ma l'indice era completamente diverso. Sembravano gli stessi dati, ma con un ordinamento diverso. E le Materialized Views consentono, se necessario, di aggirare tale vincolo di ClickHouse.
- Riduci la granularità dell'indice per le query puntuali.
- E distribuisci i dati in modo intelligente, cercando di localizzare al massimo i dati all'interno del server. E fai in modo che le query utilizzino anche la localizzazione dove possibile il più possibile.

Riassumendo questo breve intervento, si può dire che ClickHouse ha ora solidamente conquistato il territorio sia dei database commerciali che dei database open source, vale a dire, specificamente per l'analisi. Si è inserito meravigliosamente in questo panorama. Inoltre, comincia lentamente a soppiantare altri, perché quando c'è ClickHouse, non hai bisogno di InfiniDB. Verticale potrebbe presto diventare superflua, se forniscono un buon supporto per SQL. Usatelo!

—Grazie per la relazione! Molto interessante! Ci sono stati confronti con Apache Phoenix?
-No, non ho sentito che qualcuno abbia fatto un confronto. Noi e Yandex cerchiamo di seguire tutti i confronti di ClickHouse con vari database. Perché se qualcosa risulta essere più veloce di ClickHouse, allora Alexey Milovidov non riesce a dormire la notte e inizia a velocizzarlo rapidamente. Non ho sentito di un confronto del genere.
(Aleksey Milovidov) Apache Phoenix è un motore SQL su Hbase. Hbase è principalmente destinato a scenari di lavoro tipo key-value. In ogni riga può esserci un numero arbitrario di colonne con nomi arbitrari. Questo vale per sistemi come Hbase e Cassandra. E su di essi le richieste analitiche pesanti non funzioneranno bene. Oppure potresti pensare che funzionino bene, se non hai avuto esperienza con ClickHouse.
Grazie
Buongiorno! Sono interessato a questo argomento da un po', perché ho un sottosistema analitico. Ma quando guardo ClickHouse, ho l'impressione che ClickHouse sia molto adatto per l'analisi di eventi, di tipo mutable. E se devo analizzare molti dati aziendali con tonnellate di grandi tabelle, ClickHouse, per quello che capisco, non mi sembra molto adatto? Soprattutto se questi dati cambiano. È corretto o ci sono esempi che possono smentirlo?
È corretto. E questo è vero per la maggior parte dei database analitici specializzati. Sono progettati per avere una o più grandi tabelle, che sono mutevoli, e molte piccole, che cambiano lentamente. Cioè, ClickHouse non è come Oracle, dove puoi mettere tutto e costruire query molto complesse. Per utilizzare ClickHouse in modo efficace, devi costruire lo schema in un modo che funzioni bene in ClickHouse. Cioè, evitare un'eccessiva normalizzazione, utilizzare dizionari e cercare di avere meno collegamenti lunghi. E se costruisci lo schema in questo modo, allora compiti aziendali simili su ClickHouse possono essere risolti in modo molto più efficiente rispetto a un tradizionale database relazionale.
Grazie per la relazione! Ho una domanda sull'ultimo caso finanziario. Avevano un'analisi. Dovevano confrontare come si muovono su e giù. E capisco che avete costruito il sistema proprio per questa analisi? Se domani, per esempio, avessero bisogno di un altro report su questi dati, devono ricostruire lo schema e ricaricare i dati? Cioè, fare una qualche pre-elaborazione per ottenere la query?
Certo, è un utilizzo di ClickHouse per un compito molto specifico. Questo potrebbe essere risolto in modo più tradizionale nell'ambito di Hadoop. Per Hadoop, è un compito ideale. Ma su Hadoop è molto lento. E il mio obiettivo è dimostrare che su ClickHouse è possibile risolvere compiti che di solito sono affrontati con strumenti completamente diversi, ma in modo molto più efficiente. È dedicato a un compito specifico. È chiaro che se c'è un compito simile, può essere risolto in modo simile.
Capisco. Hai detto che sono stati necessari 50 ore per l'elaborazione. Questi tempi partono dall'inizio, quando sono stati caricati i dati o dall'arrivo dei risultati?
Sì-sì.
Va bene, grazie mille.
Questo su un cluster di 3 server.
Salve! Grazie per la relazione! È tutto molto interessante. Vorrei chiedere non tanto sul funzionamento, quanto sull'uso di ClickHouse in termini di stabilità. Cioè, si sono verificati problemi, avete dovuto ripristinare? Come si comporta ClickHouse in questo caso? E si è verificato che vi sia stata una caduta e anche la replica? Noi, per esempio, abbiamo riscontrato problemi con ClickHouse quando supera il suo limite e va in crash.
Certo, non esistono sistemi perfetti. E anche ClickHouse ha i suoi problemi. Ma avete mai sentito che Yandex.Metrica non ha funzionato a lungo? Probabilmente no. Funziona in modo affidabile da circa il 2012-2013 su ClickHouse. Posso anche dire qualcosa sulla mia esperienza. Non abbiamo mai avuto interruzioni complete. Alcuni problemi parziali potrebbero verificarsi, ma non sono mai stati critici al punto da influenzare seriamente il business. Non è mai successo. ClickHouse è abbastanza affidabile e non si blocca casualmente. Non c'è bisogno di preoccuparsi di questo. Non è una cosa grezza. È stato dimostrato da molte aziende.
Buongiorno! Hai detto che è necessario pensare bene allo schema dei dati sin dall'inizio. E se è successo? I miei dati stanno arrivando incessantemente. Passano sei mesi e capisco che non posso continuare così, devo ricaricare i dati e fare qualcosa con essi.
Dipende, ovviamente, dal tuo sistema. Ci sono diversi modi per farlo praticamente senza interruzioni. Ad esempio, puoi creare una Materialized View, in cui impostare una struttura dati diversa, se può essere mappata in modo chiaro. Vale a dire, se permette il mapping tramite ClickHouse, cioè estrarre alcune cose, cambiare la chiave primaria, modificare la partizione, allora puoi creare una Materialized View. Lì puoi riscrivere i tuoi vecchi dati, i nuovi verranno scritti automaticamente. E poi puoi semplicemente passare all'utilizzo della Materialized View, poi cambiare la scrittura e eliminare la tabella vecchia. Questo è un modo per farlo senza interruzioni.
Grazie.
Fonte: habr.com
