{"id":91438,"date":"2020-08-13T19:42:36","date_gmt":"2020-08-13T17:42:36","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/effektivnoe-ispolzovanie-clickhouse-aleksej-milovidov-yandeks"},"modified":"2020-08-13T19:42:36","modified_gmt":"2020-08-13T17:42:36","slug":"effektivnoe-ispolzovanie-clickhouse-aleksej-milovidov-yandeks","status":"publish","type":"post","link":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/effektivnoe-ispolzovanie-clickhouse-aleksej-milovidov-yandeks","title":{"rendered":"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/8e42c1fffffcc964eacef240ea90bbc5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Poich\u00e9 ClickHouse \u00e8 un sistema specializzato, \u00e8 importante considerare le peculiarit\u00e0 della sua architettura durante il suo utilizzo. In questo rapporto, Aleksey parler\u00e0 di esempi di errori tipici nell'uso di ClickHouse, che possono portare a performance inefficaci. Attraverso esempi pratici, verr\u00e0 mostrato come la scelta di uno schema di elaborazione dei dati piuttosto che un altro possa influenzare notevolmente le prestazioni.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Ciao a tutti! Mi chiamo Aleksey e lavoro con ClickHouse.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/7f5fc01663be58d3d25e518a4169b8cf.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Innanzitutto, sono felice di dirvi che oggi non vi parler\u00f2 di cosa sia ClickHouse. A dire il vero, mi sono stancato di farlo. Ogni volta spiego cosa sia. E probabilmente tutti ormai lo sanno. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/fae6bd07d098200643d591b8e5bf51e8.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Invece, parler\u00f2 di quali sono le possibili insidie, cio\u00e8 come \u00e8 possibile utilizzare ClickHouse in modo errato. In realt\u00e0, non c'\u00e8 motivo di preoccuparsi, perch\u00e9 stiamo sviluppando ClickHouse come un sistema semplice, comodo, che funziona out-of-the-box. Installato e via, nessun problema. <\/p>\n<p><\/p>\n<p>Tuttavia, \u00e8 comunque necessario considerare che questo \u00e8 un sistema specializzato e si pu\u00f2 facilmente imbattersi in uno scenario d'uso insolito che porter\u00e0 questo sistema fuori dalla sua zona di comfort.<\/p>\n<p><\/p>\n<p>Quindi, quali sono le insidie? Principalmente parler\u00f2 di cose ovvie. Per tutti \u00e8 tutto chiaro, tutti capiscono e possono essere contenti di essere cos\u00ec intelligenti, e chi non capisce, scoprir\u00e0 qualcosa di nuovo. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/bffacf353ff31b361460178e911f0e16.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Il primo esempio molto semplice, che purtroppo si incontra frequentemente, \u00e8 un grande numero di inserti con piccoli batch, cio\u00e8 un gran numero di inserti piccoli.<\/p>\n<p><\/p>\n<p>Se consideriamo come ClickHouse esegue un inserimento, potete inviare un flusso di dati fino a un terabyte in una sola richiesta. Non \u00e8 un problema. <\/p>\n<p><\/p>\n<p>E diamo un'occhiata a quale sar\u00e0 la prestazione tipica. Ad esempio, abbiamo una tabella con dati di Yandex.Metrica. Hit. 105 colonne diverse. 700 byte in forma non compressa. E inseriremo in modo corretto batch di un milione di righe. <\/p>\n<p><\/p>\n<p>Inserendo nella tabella MergeTree, otteniamo mezzo milione di righe al secondo. Ottimo. Nella tabella replicata, sar\u00e0 leggermente inferiore, circa 400.000 righe al secondo. <\/p>\n<p><\/p>\n<p>E se attiviamo l'inserimento a maggioranza, otteniamo qualcosa di meno, ma comunque una prestazione decente, 250.000 righe al secondo. L'inserimento a maggioranza \u00e8 una funzionalit\u00e0 non documentata in ClickHouse*.<\/p>\n<p><\/p>\n<p>* al 2020, <noindex><a rel=\"nofollow\" href=\"https:\/\/clickhouse.tech\/docs\/en\/operations\/settings\/settings\/#settings-insert_quorum\">gi\u00e0 documentata<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/668498fc82a0f6e851d05e6e1ea67033.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Cosa succede se si fa male? Inseriamo una riga alla volta nella tabella MergeTree e otteniamo 59 righe al secondo. Questo \u00e8 10.000 volte pi\u00f9 lento. Nel ReplicatedMergeTree \u2013 6 righe al secondo. E se si attiva anche il quorum, otteniamo 2 righe al secondo. A mio parere, \u00e8 un autentico disastro. Come si pu\u00f2 rallentare in questo modo? Ho persino una maglietta con scritto che ClickHouse non deve rallentare. Tuttavia, succede comunque a volte. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/4c771eddc4e8453f60ef91123ae5d109.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>In realt\u00e0, \u00e8 la nostra mancanza. Potremmo facilmente fare in modo che tutto funzioni correttamente, ma non lo abbiamo fatto. E non l'abbiamo fatto perch\u00e9 per il nostro scenario non era necessario. Avevamo gi\u00e0 dei batch. I batch arrivavano da noi senza problemi. Inseriamo e tutto funziona normalmente. Ma, ovviamente, possono esserci vari scenari. Ad esempio, quando hai un sacco di server dove vengono generati i dati. E inseriscono i dati non cos\u00ec frequentemente, ma ci sono comunque inserimenti frequenti. E bisogna in qualche modo evitarlo. <\/p>\n<p><\/p>\n<p>Da un punto di vista tecnico, la questione \u00e8 che quando si esegue un inserimento in ClickHouse, i dati non finiscono in alcun memtable. Non abbiamo nemmeno un vero log structure MergeTree, ma solo un MergeTree, perch\u00e9 non ci sono log n\u00e9 memTable. Scriviamo direttamente i dati nel file system, gi\u00e0 distribuiti in colonne. E se hai 100 colonne, dovrai scrivere pi\u00f9 di 200 file in una directory separata. \u00c8 tutto abbastanza ingombrante. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/24688fe3d39d81b92f12ac1b8b21425b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>E sorge la domanda: \u00abCome si fa correttamente?\u00bb, se abbiamo questa situazione dove dobbiamo comunque scrivere i dati in ClickHouse.<\/p>\n<p><\/p>\n<p>Metodo 1. Questo \u00e8 il modo pi\u00f9 semplice. Usare qualche coda distribuita. Ad esempio, Kafka. Semplicemente estrai i dati da Kafka, batch ogni secondo. E tutto andr\u00e0 bene, scrivi e tutto funzioner\u00e0 normalmente. <\/p>\n<p><\/p>\n<p>Gli svantaggi sono che Kafka \u00e8 un'altra pesante sistema distribuito. Posso capire se in azienda hai gi\u00e0 Kafka. \u00c8 utile, \u00e8 comodo. Ma se non ce l'hai, vale la pena riflettere tre volte prima di portare un altro sistema distribuito nel tuo progetto. Pertanto, \u00e8 meglio considerare alternative. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/4f687221e8c7443abf02fb002c4eba5b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Metodo 2. Ecco un'alternativa old school, molto semplice. Hai un server che genera i tuoi log. Il server registra semplicemente i log in un file. E una volta al secondo, ad esempio, rinominiamo questo file e ne apriamo uno nuovo. Un'apposita script, tramite cron o un daemon, prende il file pi\u00f9 vecchio e lo registra in ClickHouse. Se registri i log ogni secondo, va tutto alla grande. <\/p>\n<p><\/p>\n<p>Ma il difetto di questo metodo \u00e8 che se il tuo server, dove vengono generati i log, scompare, anche i dati andranno persi.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/b4c28b6df87386c42b6908bdfccb6b90.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Metodo 3. C'\u00e8 un altro modo interessante, senza file temporanei. Ad esempio, hai uno script di pubblicit\u00e0 o un altro daemon interessante che genera dati. Puoi accumulare un insieme di dati direttamente in memoria, nel buffer. E quando trascorre un periodo di tempo sufficiente, tieni da parte quel buffer, crei uno nuovo, e in un thread separato inserisci ci\u00f2 che \u00e8 gi\u00e0 accumulato in ClickHouse.<\/p>\n<p><\/p>\n<p>D'altra parte, i dati scompaiono anche con un kill -9. Se il tuo server va gi\u00f9, perderai quei dati. Inoltre, c'\u00e8 un problema: se non riesci a registrare nel database, i dati si accumuleranno in memoria. E o finisci la memoria, o semplicemente perdi i dati. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/dc375b22fcb26cfa111d0bdb4563aa88.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Metodo 4. Un altro modo interessante. Hai un qualche processo server. Pu\u00f2 inviare dati a ClickHouse direttamente, ma farlo in una sola connessione. Ad esempio, invia una richiesta http con transfer-encoding: chunked con un'operazione di insert. E genera i chunk non troppo raramente; puoi inviare ogni riga, anche se ci sar\u00e0 un overhead per il framing di questi dati. <\/p>\n<p><\/p>\n<p>Tuttavia, in questo caso, i dati verranno inviati a ClickHouse immediatamente. E ClickHouse li bufferizzer\u00e0 da solo. <\/p>\n<p><\/p>\n<p>Ma si presentano anche dei problemi. Adesso perderai dati, inclusi quelli quando il tuo processo si ferma e, se il processo ClickHouse si interrompe, perch\u00e9 sar\u00e0 un insert non completato. In ClickHouse, gli insert sono atomici fino a un certo limite specificato in termini di righe. In linea di principio, \u00e8 un modo interessante. Pu\u00f2 essere utilizzato anche questo.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/6a18a974b9600ade377a870390e95d3d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Metodo 5. Ecco un altro modo interessante. \u00c8 un server sviluppato dalla community per il batching dei dati. Non l'ho esaminato personalmente, quindi non posso garantire nulla. Tuttavia, anche per ClickHouse non vengono fornite garanzie. Anche questo \u00e8 open source, ma d'altra parte, potresti essere abituato a uno standard di qualit\u00e0 che cerchiamo di garantire. Per questa cosa, non so, vai su GitHub, guarda il codice. Potrebbe essere stato scritto qualcosa di decente. <\/p>\n<p><\/p>\n<p>* a partire dal 2020, occorre anche aggiungere da considerare <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/en\/company\/vk\/blog\/430168\/\">KittenHouse<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/ae6a04af63ae4e7fa160c002fdb6d506.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Metodo 6. Un altro metodo \u00e8 l'uso delle tabelle Buffer. I vantaggi di questo metodo sono che \u00e8 molto semplice iniziare a utilizzarlo. Crei una tabella Buffer e ci inserisci dati. <\/p>\n<p><\/p>\n<p>Ma lo svantaggio \u00e8 che il problema non viene risolto completamente. Se, durante l'inserimento con MergeTree, devi raggruppare i dati a un batch al secondo, con l'inserimento nella tabella buffer, devi raggruppare almeno fino a qualche migliaio al secondo. Se ci sono pi\u00f9 di 10.000 al secondo, andr\u00e0 comunque male. E se inserisci a batch, hai visto che arrivano a centinaia di migliaia di righe al secondo. E questo gi\u00e0 con dati piuttosto pesanti. <\/p>\n<p><\/p>\n<p>E anche le tabelle buffer non hanno un log. E se c'\u00e8 qualcosa che non va con il tuo server, i dati andranno persi. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/9bb16bf5e8145cc8368b11e54c86c837.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>E come bonus, recentemente in ClickHouse \u00e8 stata introdotta la possibilit\u00e0 di prelevare dati da Kafka. C'\u00e8 un motore di tabelle \u2013 Kafka. Devi solo crearlo. E su di esso puoi montare viste materializzate. In questo caso, prelever\u00e0 automaticamente i dati da Kafka e li inserir\u00e0 nelle tabelle che desideri. <\/p>\n<p><\/p>\n<p>E ci\u00f2 che \u00e8 particolarmente rassicurante in questa funzionalit\u00e0 \u00e8 che non l'abbiamo realizzata noi. \u00c8 una funzione della community. E quando dico \"funzione della community\", lo dico senza alcun disprezzo. Abbiamo letto il codice, abbiamo fatto la revisione, dovrebbe funzionare normalmente. <\/p>\n<p><\/p>\n<p>* a partire dal 2020, \u00e8 stata introdotta un'analoga supporto per <noindex><a rel=\"nofollow\" href=\"https:\/\/clickhouse.tech\/docs\/en\/engines\/table-engines\/integrations\/rabbitmq\/\">RabbitMQ<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/15dc61dfd435f5f8640395b7de480fe2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Cosa altro potrebbe essere scomodo o inaspettato durante l'inserimento dei dati? Se fai una richiesta insert values e nel values scrivi alcune espressioni calcolate. Ad esempio, now() \u00e8 anch'essa un'espressione calcolata. E in questo caso ClickHouse \u00e8 costretto a eseguire l'interprete di queste espressioni per ogni riga, e le prestazioni caleranno drasticamente. \u00c8 meglio evitarlo.<\/p>\n<p><\/p>\n<p>* Al momento, il problema \u00e8 completamente risolto, non ci sono pi\u00f9 regressioni nelle prestazioni quando si utilizzano espressioni in VALUES.<\/p>\n<p><\/p>\n<p>Un altro esempio di quando potrebbero esserci alcuni problemi \u00e8 quando in un unico batch i dati appartengono a pi\u00f9 partizioni. Per impostazione predefinita, in ClickHouse le partizioni sono mensili. Se si inserisce un batch di un milione di righe, e i dati coprono alcuni anni, si avr\u00e0 a che fare con diverse decine di partizioni. Questo equivale ad avere batch di dimensioni diverse, poich\u00e9 all'interno vengono sempre prima suddivisi per partizioni.<\/p>\n<p><\/p>\n<p>* Recentemente, in ClickHouse, \u00e8 stata aggiunta in modalit\u00e0 sperimentale la supporto per il formato compatto dei pezzi e dei pezzi in memoria con write-ahead log, il che risolve quasi completamente il problema.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/b8c6cecdba53559dad31ed11713a980d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ora consideriamo il secondo tipo di problema: la tipizzazione dei dati. <\/p>\n<p><\/p>\n<p>La tipizzazione dei dati pu\u00f2 essere rigorosa oppure stringa. Stringa significa che hai semplicemente dichiarato che tutti i campi sono di tipo string. Questo non va bene. Non si dovrebbe fare cos\u00ec. <\/p>\n<p><\/p>\n<p>Vediamo come fare correttamente nei casi in cui vogliamo specificare che un campo \u00e8 una stringa, e lasciare che ClickHouse si occupi del resto, senza preoccuparci troppo. Tuttavia, vale la pena fare alcuni sforzi. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/a0fdcf6423933293318411242fe2ede7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ad esempio, abbiamo un indirizzo IP. In un caso lo abbiamo salvato come stringa, ad esempio 192.168.1.1. In un altro caso, sar\u00e0 un numero di tipo UInt32*. 32 bit sono sufficienti per un indirizzo IPv4.<\/p>\n<p><\/p>\n<p>Innanzitutto, sorprendentemente, i dati si comprimono in modo simile. Ci sar\u00e0 ovviamente qualche differenza, ma non cos\u00ec significativa. Pertanto, non ci sono particolari problemi con l'ingresso\/uscita su disco. <\/p>\n<p><\/p>\n<p>Tuttavia, c'\u00e8 una notevole differenza nel tempo di CPU e nel tempo di esecuzione della query. <\/p>\n<p><\/p>\n<p>Calcoliamo il numero di indirizzi IP unici, se sono memorizzati come numeri. Risulta 137 milioni di righe al secondo. Se lo stesso viene fatto come stringhe, si arriva a 37 milioni di righe al secondo. Non so perch\u00e9 ci sia questa corrispondenza. Io stesso ho eseguito queste query. Tuttavia, risulta essere circa 4 volte pi\u00f9 lento. <\/p>\n<p><\/p>\n<p>E se si calcola la differenza nello spazio su disco, c'\u00e8 anche una differenza. E questa differenza \u00e8 di circa un quarto, poich\u00e9 ci sono molti indirizzi IP unici. Se ci fossero stringhe con un numero ridotto di valori diversi, si comprimeranno facilmente in modo simile a un dizionario occupando circa lo stesso spazio. <\/p>\n<p><\/p>\n<p>E la differenza di quattro volte nel tempo di viaggio non \u00e8 da prendere alla leggera. Forse a te non importa, ma quando vedo una tale differenza, mi sento triste.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/f74dbfdab5a9e26fa044a5870a8cc00d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Consideriamo diversi casi. <\/p>\n<p><\/p>\n<p>1. Un caso \u00e8 quando hai pochi valori unici. In questo caso utilizziamo una pratica semplice che probabilmente conosci e puoi usare per qualsiasi DBMS. Questo ha senso non solo per ClickHouse. Semplicemente registri in un database identificatori numerici. E la conversione in stringhe e viceversa pu\u00f2 avvenire sul lato della tua applicazione. <\/p>\n<p><\/p>\n<p>Ecco, ad esempio, hai una regione. E provi a salvarla come stringa. E ci sar\u00e0 scritto: Mosca e MO. E quando vedo che c'\u00e8 scritto 'Mosca', va ancora bene, ma quando c'\u00e8 anche MO, diventa davvero triste. Quanti byte sono necessari. <\/p>\n<p><\/p>\n<p>Invece, scriviamo semplicemente il numero Ulnt32 e 250. Abbiamo 250 in Yandex, mentre per te potrebbe essere diverso. Dico per sicurezza che in ClickHouse c'\u00e8 una funzionalit\u00e0 integrata per lavorare con le geodatabase. Basta registrare un elenco di regioni, inclusa la gerarchia, cio\u00e8 ci sar\u00e0 Mosca, MO e tutto ci\u00f2 di cui hai bisogno. E puoi effettuare la conversione a livello di query. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/cc6e871136dab8f8a35246a5af512cda.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>La seconda opzione \u00e8 simile, ma gi\u00e0 con supporto interno in ClickHouse. Questo \u00e8 il tipo di dato Enum. Scrivi semplicemente all'interno di Enum tutti i valori di cui hai bisogno. Ad esempio, il tipo di dispositivo e scrivi: desktop, mobile, tablet, televisore. Solo 4 opzioni. <\/p>\n<p><\/p>\n<p>Il problema \u00e8 che devi periodicamente fare alter. Hai aggiunto solo un'opzione. Fai alter table. In realt\u00e0, alter table in ClickHouse \u00e8 gratuito. Soprattutto \u00e8 gratuito per Enum, poich\u00e9 i dati su disco non cambiano. Tuttavia, l'alter provoca un blocco sulla tabella e deve attendere che tutte le selezioni siano completate. Solo dopo che questi sono stati completati, l'alter avr\u00e0 successo, quindi ci sono comunque alcuni inconvenienti.<\/p>\n<p><\/p>\n<p>* nelle versioni pi\u00f9 recenti di ClickHouse, ALTER \u00e8 completamente non bloccante.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/d7284fa5be583ab063bb6de0b60f54d4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Un'altra opzione abbastanza unica per ClickHouse \u00e8 l'integrazione di dizionari esterni. Puoi scrivere in ClickHouse numeri e mantenere i tuoi dizionari in qualsiasi sistema ti sia pi\u00f9 comodo. Ad esempio, puoi utilizzare: MySQL, Mongo, Postgres. Puoi anche sviluppare un tuo microservizio che fornisca questi dati tramite http. E a livello di ClickHouse scrivi una funzione che convertir\u00e0 questi dati da numeri a stringhe. <\/p>\n<p><\/p>\n<p>Questo \u00e8 un modo specializzato, ma molto efficace per eseguire un join con una tabella esterna. Esistono due varianti. In una variante, questi dati saranno completamente memorizzati nella cache, completamente presenti in memoria e aggiornati con una certa periodicit\u00e0. Nell'altra variante, se i dati non possono essere memorizzati in memoria, sar\u00e0 possibile memorizzarli parzialmente nella cache. <\/p>\n<p><\/p>\n<p>Ecco un esempio. C'\u00e8 Yandex.Direct, dove ci sono campagne pubblicitarie e banner. Le campagne pubblicitarie sono probabilmente circa dieci milioni e possono essere memorizzate in memoria. I banner, invece, sono miliardi e non possono essere memorizzati. Utilizziamo un dizionario memorizzabile nella cache da MySQL.<\/p>\n<p><\/p>\n<p>L'unico problema \u00e8 che il dizionario memorizzabile nella cache funzioner\u00e0 correttamente solo se il tasso di hit \u00e8 vicino al 100%. Se \u00e8 inferiore, durante l'elaborazione delle richieste per ogni gruppo di dati sar\u00e0 necessario prelevare effettivamente le chiavi mancanti e recuperare i dati da MySQL. Per quanto riguarda ClickHouse, posso assicurare che non rallenta, ma non parler\u00f2 di altri sistemi.<\/p>\n<p><\/p>\n<p>Inoltre, come bonus, i dizionari sono un modo molto semplice per aggiornare i dati in ClickHouse retroattivamente. Cio\u00e8, se avevi un report su campagne pubblicitarie, e un utente cambia semplicemente la campagna pubblicitaria, tutti i dati vecchi e i report verranno aggiornati con queste nuove informazioni. Se scrivi righe direttamente nella tabella, sar\u00e0 impossibile aggiornarl. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/a5a2919d6be7d00c0ad5875b9a8f0f31.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Un altro modo \u00e8 quando non sai da dove prendere gli identificatori per le tue righe. Puoi semplicemente creare un hash. Il modo pi\u00f9 semplice \u00e8 utilizzare un hash a 64 bit. <\/p>\n<p><\/p>\n<p>L'unico problema \u00e8 che se l'hash \u00e8 a 64 bit, le collisioni si verificheranno quasi sicuramente. Perch\u00e9 se ci sono miliardi di righe, la probabilit\u00e0 diventa significativa. <\/p>\n<p><\/p>\n<p>Non sarebbe molto opportuno fare cos\u00ec per creare hash dei nomi delle campagne pubblicitarie. Se i nomi delle campagne pubblicitarie vengono confusi tra diverse aziende, ci sar\u00e0 qualcosa di incomprensibile. <\/p>\n<p><\/p>\n<p>E c'\u00e8 un trucco semplice. Certo, non \u00e8 molto adatto per dati importanti, ma se hai qualcosa di meno serio, aggiungi semplicemente l'identificativo del cliente alla chiave del dizionario. E allora avrai delle collisioni, ma solo all'interno di un singolo cliente. Questo metodo \u00e8 utilizzato per la mappa dei link in Yandex.Metrica. Abbiamo URL l\u00ec, conserviamo gli hash. E sappiamo che le collisioni ci sono, ovviamente. Ma quando la pagina viene visualizzata, la probabilit\u00e0 che su una singola pagina un utente abbia degli URL collisi e che venga notato \u00e8 da trascurare. <\/p>\n<p><\/p>\n<p>Come bonus \u2013 per molte operazioni bastano solo gli hash e le stringhe non devono essere archiviate da nessuna parte. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/abbb73aaba29d10e3b7e7650bf68e6a6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Un altro esempio \u00e8 se le stringhe sono corte, ad esempio, i domini dei siti. Possono essere memorizzati cos\u00ec come sono. Oppure, ad esempio, la lingua del browser ru \u2013 2 byte. Certo, mi dispiace per i byte, ma non preoccuparti, 2 byte non sono un problema. Per favore, memorizza cos\u00ec com'\u00e8, non farti problemi. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/901eaed0029da6ea59630b57ccf80c25.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Un'altra situazione \u00e8 quando ci sono molte stringhe e in esse tante sono uniche, e il numero potenziale non \u00e8 limitato. Un esempio tipico sono le frasi di ricerca o gli URL. Le frasi di ricerca, anche a causa di errori di battitura. Vediamo quante frasi di ricerca uniche ci sono in un giorno. Risulta che quasi met\u00e0 di tutti gli eventi sono queste. E in questo caso, potresti pensare che sia necessario normalizzare i dati, calcolare gli identificatori, metterli in una tabella separata. Ma non \u00e8 necessario fare cos\u00ec. Semplicemente memorizza queste stringhe cos\u00ec come sono. <\/p>\n<p><\/p>\n<p>Meglio \u2013 non inventare nulla, perch\u00e9 se si memorizza separatamente, sar\u00e0 necessario fare un join. E questo join \u2013 nel migliore dei casi un accesso casuale in memoria, se ci sta ancora in memoria. Se non ci sta, ci saranno problemi. <\/p>\n<p><\/p>\n<p>E se i dati sono memorizzati in in place, vengono semplicemente letti nell'ordine necessario dal file system e tutto va bene.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/15f1d632083def16ccbc939579c1cf6b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Se hai URL o qualche altra stringa lunga e complessa, vale la pena considerare che puoi calcolare un'estrazione in anticipo e registrarla in una colonna separata. <\/p>\n<p><\/p>\n<p>Per gli URL, ad esempio, puoi memorizzare separatamente il dominio. E se hai davvero bisogno del dominio, basta utilizzare questa colonna, mentre gli URL rimarranno qui, e non dovrai nemmeno toccarli. <\/p>\n<p><\/p>\n<p>Vediamo che differenza c'\u00e8. In ClickHouse c'\u00e8 una funzione specializzata che calcola il dominio. \u00c8 molto veloce e l'abbiamo ottimizzata. E, a dirla tutta, non corrisponde nemmeno all'RFC, eppure calcola tutto ci\u00f2 di cui abbiamo bisogno. <\/p>\n<p><\/p>\n<p>In un caso, estrarremo semplicemente gli URL e calcoleremo il dominio. Ci vogliono 166 millisecondi. Se prendiamo un dominio pronto, ci vogliono solo 67 millisecondi, cio\u00e8 quasi tre volte pi\u00f9 veloce. E questo non \u00e8 dovuto a calcoli, ma al fatto che leggiamo meno dati. <\/p>\n<p><\/p>\n<p>Per qualche motivo, un'interrogazione che \u00e8 pi\u00f9 lenta risulta avere una maggiore velocit\u00e0 in gigabyte al secondo. Perch\u00e9 legge pi\u00f9 gigabyte. Questi sono dati completamente superflui. L'interrogazione sembra funzionare pi\u00f9 velocemente, ma richiede pi\u00f9 tempo per essere eseguita.<\/p>\n<p><\/p>\n<p>Se guardiamo la dimensione dei dati su disco, scopriamo che l'URL occupa 126 megabyte, mentre il dominio solo 5 megabyte. Questo \u00e8 quindi 25 volte meno. Tuttavia, l'interrogazione viene eseguita solo 4 volte pi\u00f9 velocemente. Questo \u00e8 perch\u00e9 i dati sono 'caldi'. Se fossero stati 'freddi', sarebbe sicuramente stato 25 volte pi\u00f9 veloce a causa dell'input\/output del disco. <\/p>\n<p><\/p>\n<p>A proposito, se valutiamo quanto il dominio sia pi\u00f9 piccolo dell'URL, risulta circa 4 volte. Ma per qualche motivo, i dati su disco occupano 25 volte meno. Perch\u00e9? A causa della compressione. Sia l'URL che il dominio vengono compressi. Tuttavia, spesso l'URL contiene un sacco di spazzatura. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/c93d2128a41561ed7abb25d77414bc2d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>E, ovviamente, \u00e8 fondamentale utilizzare i tipi di dati corretti, progettati specificamente per i valori necessari o che si adattano. Se si tratta di IPv4, memorizzate UInt32*. Se \u00e8 IPv6, allora FixedString(16), perch\u00e9 un indirizzo IPv6 \u00e8 lungo 128 bit, cio\u00e8 memorizzate direttamente in formato binario. <\/p>\n<p><\/p>\n<p>E cosa fare se avete talvolta indirizzi IPv4 e talvolta IPv6? S\u00ec, potete memorizzare entrambi. Una colonna per IPv4, un'altra per IPv6. Certamente, c'\u00e8 l'opzione di rappresentare l'IPv4 in IPv6. Questo funzioner\u00e0 comunque, ma se nelle interrogazioni avete spesso bisogno dell'indirizzo IPv4, sarebbe utile metterlo in una colonna separata. <\/p>\n<p><\/p>\n<p>* ora in ClickHouse ci sono tipi di dati separati per IPv4 e IPv6, che memorizzano i dati in modo altrettanto efficiente come i numeri, ma li rappresentano in modo altrettanto conveniente come le stringhe.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/d7d6342ebd6b8b4f3526b3cd8a06cf26.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00c8 importante notare che \u00e8 opportuno pre-elaborare i dati in anticipo. Ad esempio, se ricevi dei log grezzi. E, forse, non dovresti inserirli immediatamente in ClickHouse, anche se \u00e8 molto allettante non fare nulla e tutto funzioner\u00e0. Ma \u00e8 comunque opportuno eseguire i calcoli che \u00e8 possibile fare.<\/p>\n<p><\/p>\n<p>Ad esempio, la versione del browser. In un certo dipartimento vicino, a cui non voglio puntare il dito, la versione del browser \u00e8 memorizzata in questo modo, cio\u00e8 come stringa: 12.3. E poi, per generare un report, prendono questa stringa, la dividono per un array, e poi per il primo elemento dell'array. \u00c8 ovvio che tutto si rallenta. Ho chiesto perch\u00e9 fanno cos\u00ec. Mi hanno risposto che non amano l'ottimizzazione prematura. E io non amo la pessimit\u00e0 prematura.<\/p>\n<p><\/p>\n<p>Quindi in questo caso sarebbe pi\u00f9 corretto dividere in 4 colonne. Qui non abbiate paura, perch\u00e9 \u00e8 ClickHouse. ClickHouse \u00e8 un database a colonne. E pi\u00f9 piccole colonne pulite hai, meglio \u00e8. Se hai 5 BrowserVersion, crea 5 colonne. Va bene. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/f9a67221bf8508933d7bd336b16f9e04.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Adesso consideriamo cosa fare se hai molte stringhe molto lunghe, array molto lunghi. Non \u00e8 necessario conservarli affatto in ClickHouse. Invece puoi memorizzare in ClickHouse solo un qualche identificatore. E inserisci queste lunghe stringhe in un'altra sistema. <\/p>\n<p><\/p>\n<p>Ad esempio, in uno dei nostri servizi analitici ci sono alcuni parametri degli eventi. E se gli eventi ricevono molti parametri, salviamo semplicemente i primi 512 che capitano. Perch\u00e9 512 non \u00e8 un problema. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/755271e8788ba4bd638f493bf320c820.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>E se non riesci a decidere i tuoi tipi di dato, puoi comunque scrivere i dati in ClickHouse, ma in una tabella temporanea di tipo Log, speciale per i dati temporanei. Dopodich\u00e9 puoi analizzare quale sia la distribuzione dei valori, cosa c'\u00e8 e classificare i tipi corretti.<\/p>\n<p><\/p>\n<p>* attualmente in ClickHouse c'\u00e8 il tipo di dato <noindex><a rel=\"nofollow\" href=\"https:\/\/clickhouse.tech\/docs\/en\/sql-reference\/data-types\/lowcardinality\/\">LowCardinality<\/a><\/noindex> che consente di memorizzare efficacemente stringhe con minori costi di lavoro.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/7e9e53d86a4189783c28ce56a669198c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Adesso consideriamo un altro caso interessante. A volte per le persone tutto funziona in modo strano. Entro e vedo qualcosa del genere. E subito si presenta l'idea che questo sia stato fatto da un amministratore molto esperto e intelligente, con una grande esperienza nell'impostazione di MySQL versione 3.23. <\/p>\n<p><\/p>\n<p>Qui vediamo mille tabelle, ognuna delle quali contiene il resto di una divisione di non si sa cosa per mille. <\/p>\n<p><\/p>\n<p>In linea di principio, rispetto l'esperienza altrui e comprendo anche le sofferenze che possono derivare da questa esperienza. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/3a5e21ef2076966fcc627670485c5b3a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Le ragioni sono pi\u00f9 o meno chiare. Questi sono vecchi stereotipi che possono essersi accumulati lavorando con altri sistemi. Ad esempio, nelle tabelle MyISAM non c'\u00e8 una chiave primaria cluster. Questo modo di separare i dati potrebbe essere un disperato tentativo di ottenere la stessa funzionalit\u00e0. <\/p>\n<p><\/p>\n<p>Un'altra ragione \u00e8 che \u00e8 difficile eseguire operazioni come alter su grandi tabelle. Tutto rimarr\u00e0 bloccato. Tuttavia, nelle versioni moderne di MySQL questo problema non \u00e8 cos\u00ec grave. <\/p>\n<p><\/p>\n<p>Oppure, ad esempio, il micro-sharding, ma di questo parleremo tra poco.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/321b1d9caa8db7aca5b96e08c61d05b5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>In ClickHouse non \u00e8 necessario farlo, perch\u00e9, innanzitutto, la chiave primaria \u00e8 cluster, e i dati sono ordinati per chiave primaria. <\/p>\n<p><\/p>\n<p>A volte mi chiedono: \u00abCome cambia le prestazioni delle query di intervallo in ClickHouse in base alle dimensioni della tabella?\u00bb. Rispondo che non cambiano affatto. Ad esempio, se hai una tabella con un miliardo di righe e leggi un intervallo di un milione di righe. Tutto va bene. Se la tabella ha un trilione di righe e leggi un milione di righe, sar\u00e0 quasi la stessa cosa. <\/p>\n<p><\/p>\n<p>In secondo luogo, non \u00e8 necessario usare cose come partizioni manuali. Se accedi e guardi quello che c'\u00e8 nel filesystem, vedrai che la tabella \u00e8 un elemento piuttosto serio. E ci sono dentro cose come partizioni. Cio\u00e8, ClickHouse fa tutto per te e non devi soffrire.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/652f3742ad3a44f172d0d7302abd09f6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Alter in ClickHouse \u00e8 gratuito, se si tratta di alter add\/drop column. <\/p>\n<p><\/p>\n<p>E non vale la pena creare tabelle piccole, perch\u00e9 se hai una tabella con 10 righe o 10.000 righe, non ha importanza. ClickHouse \u00e8 un sistema che ottimizza il throughput, non la latenza, quindi elaborare 10 righe non ha senso. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/144144b4740e9c5daec80c8dadc445f9.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00c8 giusto utilizzare un'unica grande tabella. Liberati dai vecchi stereotipi, andr\u00e0 tutto bene. <\/p>\n<p><\/p>\n<p>E come bonus, nell'ultima versione \u00e8 stata introdotta la possibilit\u00e0 di creare una chiave di partizionamento arbitraria per eseguire varie operazioni di manutenzione su singole partizioni. <\/p>\n<p><\/p>\n<p>Ad esempio, \u00e8 necessario avere molte piccole tabelle, per esempio quando si ha bisogno di elaborare alcuni dati intermedi, si ricevono dei chunk e si devono effettuare trasformazioni su di essi prima di scriverli nella tabella finale. Per questo caso esiste un meraviglioso motore di tabella \u2013 StripeLog. \u00c8 simile a TinyLog, ma migliore. <\/p>\n<p><\/p>\n<p>* ora in ClickHouse c'\u00e8 anche <noindex><a rel=\"nofollow\" href=\"https:\/\/clickhouse.tech\/docs\/en\/sql-reference\/table-functions\/input\/\">la funzione tabellare input<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/d62f0b3d29876c29c6c0ba236b200186.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Un altro antipattern \u00e8 il microsharding. Ad esempio, hai bisogno di shardare dei dati e hai 5 server, ma domani ci sar\u00e0 6 server. E ti chiedi come riequilibrare questi dati. E invece di questo, li suddividi non in 5 shard, ma in 1.000 shard. E poi mappi ciascuno di questi microshard su un server separato. Quindi, ad esempio, avrai 200 ClickHouse su un server. Istanza separate su porte separate o database separati. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/3e550ef7e338b84e4394eb9fa4538769.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ma in ClickHouse non funziona molto bene. Perch\u00e9 anche un singolo instance di ClickHouse tende a utilizzare tutte le risorse disponibili del server per elaborare una singola richiesta. Cio\u00e8, hai un server e l\u00ec, ad esempio, 56 core CPU. Esegui una query che impiega un secondo, e questa utilizzer\u00e0 56 core. Ma se hai messo 200 ClickHouse su un singolo server, si risulter\u00e0 che si avvieranno 10.000 thread. In generale, sar\u00e0 tutto molto male.<\/p>\n<p><\/p>\n<p>Un'altra ragione \u00e8 che la distribuzione del lavoro tra queste istanze sar\u00e0 irregolare. Alcune termineranno prima, alcune dopo. Se tutto ci\u00f2 avvenisse in un'unica istanza, ClickHouse gestirebbe autonomamente come distribuire correttamente i dati tra i thread. <\/p>\n<p><\/p>\n<p>E un'altra ragione \u00e8 che ci sar\u00e0 comunicazione interprocesso tramite TCP. I dati dovranno essere serializzati, deserializzati e ci saranno una quantit\u00e0 enorme di microshard. Semplicemente non sar\u00e0 efficiente.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/18cacc17d22ae1cb2977c6be74769896.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Un altro antipattern, anche se \u00e8 difficile chiamarlo tale. \u00c8 un'elevata quantit\u00e0 di preaggregazione.<\/p>\n<p><\/p>\n<p>In generale, la preaggregazione \u00e8 benefica. Avevi un miliardo di righe, le hai aggregate e sono diventate 1.000 righe, e ora la query si esegue istantaneamente. Tutto magnifico. Si pu\u00f2 fare. A tal fine, in ClickHouse esiste un tipo di tabella speciale, AggregatingMergeTree, che esegue l'aggregazione incrementale durante l'inserimento dei dati. <\/p>\n<p><\/p>\n<p>Tuttavia, ci sono casi in cui pensate che possiamo aggregare i dati in questo modo e poi in quest'altro modo. E in un altro dipartimento vicino, di cui non voglio parlare, utilizzano le tabelle SummingMergeTree per sommare in base alla chiave primaria, e come chiave primaria usano circa 20 colonne. Ho cambiato per precauzione i nomi di alcune colonne per coprire la loro identit\u00e0, ma circa cos\u00ec \u00e8.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/54e3a02ab4bbce7c63ded595780ae1f6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>E sorgono tali problemi. Prima di tutto, il volume dei dati non diminuisce in modo significativo. Ad esempio, diminuisce di tre volte. Tre volte sarebbe un buon prezzo per garantirci possibilit\u00e0 illimitate di analisi, che si presentano se i dati non sono aggregati. Se i dati sono aggregati, otteniamo solo misere statistiche anzich\u00e9 analisi. <\/p>\n<p><\/p>\n<p>E cosa c'\u00e8 di particolarmente fastidioso? Che queste persone del dipartimento vicino vanno e talvolta chiedono di aggiungere un'altra colonna alla chiave primaria. Cio\u00e8, abbiamo aggregato i dati in questo modo, e ora vogliamo un po' di pi\u00f9. Ma in ClickHouse non c'\u00e8 la possibilit\u00e0 di modificare la chiave primaria. Quindi tocca scrivere degli script in C++. E non mi piacciono gli script, anche se sono in C++.<\/p>\n<p><\/p>\n<p>E se guardiamo a cosa \u00e8 stato creato ClickHouse, i dati non aggregati sono proprio quello scenario per cui \u00e8 stato concepito. Se usate ClickHouse per dati non aggregati, state facendo tutto correttamente. Se state aggregando, a volte \u00e8 perdonabile. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/09fafd4c8a3ea8c22e586cb7a5cf6564.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Un altro caso interessante sono le query in ciclo infinito. A volte mi connetto a qualche server in produzione e guardo show processlist. E ogni volta scopro che sta succedendo qualcosa di terribile. <\/p>\n<p><\/p>\n<p>Ad esempio, questo. Qui \u00e8 subito chiaro che si sarebbe potuto eseguire tutto in una sola query. Basta scrivere url in e l'elenco.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/ae03b659f178962f50e0640614517296.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Perch\u00e9 avere molte di queste query in ciclo infinito \u00e8 un problema? Se l'indice non \u00e8 utilizzato, avrete molti passaggi sugli stessi dati. Ma se l'indice \u00e8 utilizzato, ad esempio, se avete una chiave primaria in ru e scrivete url = qualcosa. E pensate che verr\u00e0 letto un solo url dalla tabella, andr\u00e0 tutto bene. Ma in realt\u00e0 no. Perch\u00e9 ClickHouse fa tutto in batch. <\/p>\n<p><\/p>\n<p>Quando ha bisogno di leggere un certo intervallo di dati, ne legge un po' di pi\u00f9, perch\u00e9 l'indice in ClickHouse \u00e8 sparso. Questo indice non permette di trovare una singola riga nella tabella, ma solo un intervallo. E i dati vengono compressi in blocchi. Per leggere una riga, \u00e8 necessario prendere un intero blocco e decomprimerlo. E se esegui un sacco di richieste, avrai molte sovrapposizioni e un sacco di lavoro verr\u00e0 eseguito di nuovo e di nuovo.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/95eef43c5b869f8b145c61ce3c616cfd.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>E come bonus, si pu\u00f2 notare che in ClickHouse non c'\u00e8 bisogno di avere paura di trasmettere anche megabyte e persino centinaia di megabyte nella sezione IN. Ricordo dalla nostra pratica che se in MySQL trasmettiamo un sacco di valori nella sezione IN, ad esempio, trasmettiamo 100 megabyte di numeri, MySQL consuma 10 gigabyte di memoria e non succede nient'altro, tutto funziona male. <\/p>\n<p><\/p>\n<p>E la seconda cosa \u00e8 che in ClickHouse, se le tue query usano l'indice, non \u00e8 mai pi\u00f9 lento di una scansione completa, ovvero se deve leggere quasi tutta la tabella, proceder\u00e0 in modo sequenziale e legger\u00e0 tutta la tabella. In generale, si regoler\u00e0 da solo.<\/p>\n<p><\/p>\n<p>Tuttavia, ci sono alcune complessit\u00e0. Ad esempio, il fatto che l'IN con una sottoquery non utilizza l'indice. Ma questo \u00e8 un nostro problema e dobbiamo correggerlo. Non c'\u00e8 nulla di fondamentale qui. Lo sistemeremo. <\/p>\n<p><\/p>\n<p>E un'altra cosa interessante \u00e8 che se hai una richiesta molto lunga e l'elaborazione delle richieste \u00e8 distribuita, questa richiesta molto lunga verr\u00e0 inviata a ogni server senza compressione. Ad esempio, 100 megabyte e 500 server. E, di conseguenza, verranno trasferiti 50 gigabyte sulla rete. Saranno trasferiti e poi verr\u00e0 eseguita con successo.<\/p>\n<p><\/p>\n<p>* gi\u00e0 utilizzato; abbiamo sistemato tutto, come promesso.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/5fcde9bf04fff0645be2530daa12743f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>E un caso piuttosto comune \u00e8 se le richieste arrivano da un'API. Ad esempio, hai creato un tuo servizio. E se il tuo servizio \u00e8 necessario a qualcuno, hai aperto un'API e gi\u00e0 dopo due giorni vedi che succede qualcosa di strano. Tutto \u00e8 sovraccarico e arrivano alcune terribili richieste che non avrebbero mai dovuto essere. <\/p>\n<p><\/p>\n<p>E qui c'\u00e8 una sola soluzione. Se hai aperto un'API, dovrai limitarla. Ad esempio, introdurre delle quote. Non ci sono altre soluzioni normali. Altrimenti, scriveranno subito uno script e ci saranno problemi. <\/p>\n<p><\/p>\n<p>E in ClickHouse c'\u00e8 una funzionalit\u00e0 speciale: il conteggio delle quote. Si pu\u00f2 anche fornire la propria chiave di quota. Questo, ad esempio, \u00e8 un identificatore interno dell'utente. E le quote verranno calcolate in modo indipendente per ognuno di essi. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/532438d0f116919e62f04e32ebbd3c45.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ora un'altra cosa interessante. Questa \u00e8 la replica manuale. <\/p>\n<p><\/p>\n<p>So di molti casi in cui, nonostante ClickHouse abbia un supporto integrato per la replica, le persone replicano ClickHouse manualmente.<\/p>\n<p><\/p>\n<p>Qual \u00e8 il principio? Avete un pipeline di elaborazione dei dati. E funziona in modo indipendente, ad esempio, in diversi data center. Scrivete gli stessi dati nello stesso modo in ClickHouse. Tuttavia, la pratica dimostra che i dati tendono comunque a divergere a causa di alcune peculiarit\u00e0 nel vostro codice. Spero che nel vostro caso non accada. <\/p>\n<p><\/p>\n<p>E periodicamente dovrete comunque sincronizzare manualmente. Ad esempio, una volta al mese gli amministratori eseguono rsync.<\/p>\n<p><\/p>\n<p>In realt\u00e0, \u00e8 molto pi\u00f9 semplice utilizzare la replica integrata di ClickHouse. Ma ci possono essere alcune controindicazioni, perch\u00e9 per fare ci\u00f2 \u00e8 necessario utilizzare ZooKeeper. Non dir\u00f2 niente di male su ZooKeeper, in linea di massima \u00e8 un sistema funzionante, ma a volte le persone non lo utilizzano a causa della java-fobia, perch\u00e9 ClickHouse \u00e8 un ottimo sistema scritto in C++ che funziona bene. E ZooKeeper \u00e8 in java. E in qualche modo non sembra nemmeno utile, ma allora potete usare la replica manuale. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/3b5b68996daef6b8920f067b189f25e0.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>ClickHouse \u00e8 un sistema pratico. Tiene conto delle vostre esigenze. Se avete una replica manuale, potete creare una tabella Distribuita che osserva le vostre repliche manuali e gestisce autonomamente il failover tra di esse. E c'\u00e8 anche un'opzione speciale che permette di evitare fluttuazioni, anche se le vostre repliche divergono sistematicamente.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/70f6630f8b14756163923a7db8dd7391.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>In seguito possono sorgere problemi se utilizzate motori di tabella primitiva. ClickHouse \u00e8 un costruttore che offre un sacco di diversi motori di tabelle. Per tutti i casi seri, come indicato nella documentazione, utilizzate le tabelle della famiglia MergeTree. E tutte le altre sono cos\u00ec, per casi specifici o per test.<\/p>\n<p><\/p>\n<p>Nella tabella MergeTree non \u00e8 necessario avere una data e un orario specifici. Potete comunque utilizzarla. Se non ci sono data e ora, indicatelo come default \u2013 l'anno 2000. Questo funzioner\u00e0 e non richieder\u00e0 risorse. <\/p>\n<p><\/p>\n<p>E nella nuova versione del server \u00e8 anche possibile specificare un partizionamento personalizzato senza chiave di partizione. Sar\u00e0 la stessa cosa. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/6d4046d11afdd1e5962d49a1612b666a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>D'altra parte, \u00e8 possibile utilizzare motori di tabella primitivi. Ad esempio, caricare i dati una sola volta e vedere, provare e cancellare. Puoi utilizzare Log.<\/p>\n<p><\/p>\n<p>Oppure memorizzare piccole quantit\u00e0 per elaborazioni intermedie \u2013 questo \u00e8 StripeLog o TinyLog.<\/p>\n<p><\/p>\n<p>Memory pu\u00f2 essere usato se il volume dei dati \u00e8 piccolo e puoi semplicemente lavorare su qualcosa in RAM. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/8a3d4e0e3a8c26dd3a2b2f64123e2bf9.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>ClickHouse non ama molto i dati troppo normalizzati. <\/p>\n<p><\/p>\n<p>Ecco un esempio tipico. Si tratta di un gran numero di URL. Li hai messi in una tabella separata. E poi hai deciso di fare un JOIN con loro, ma questo non funzioner\u00e0, in genere, perch\u00e9 ClickHouse supporta solo Hash JOIN. Se la RAM non \u00e8 sufficiente per un grande numero di dati da unire, il JOIN non sar\u00e0 possibile*. <\/p>\n<p><\/p>\n<p>Se i dati sono di alta cardinalit\u00e0, non preoccuparti, conservali in forma denormalizzata, URL direttamente in place nella tabella principale. <\/p>\n<p><\/p>\n<p>* ora in ClickHouse c'\u00e8 anche merge join e funziona in condizioni in cui i dati intermedi non entrano nella RAM. Ma non \u00e8 efficiente e rimane valida la raccomandazione.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/e8160a8db17c18d48f810092c55b094c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ecco un altro paio di esempi, ma ormai ho dei dubbi se siano antipattern o meno. <\/p>\n<p><\/p>\n<p>In ClickHouse c'\u00e8 un noto difetto. Non supporta gli aggiornamenti*. In un certo senso, questo \u00e8 anche positivo. Se hai dati importanti, ad esempio, contabilit\u00e0, non possono essere inviati, perch\u00e9 non ci sono aggiornamenti.<\/p>\n<p><\/p>\n<p>* \u00e8 stata da tempo aggiunta la supporto per aggiornamenti e cancellazioni in modalit\u00e0 batch.<\/p>\n<p><\/p>\n<p>Ma ci sono alcuni metodi speciali che consentono di fare aggiornamenti in background. Ad esempio, tabelle tipo ReplaceMergeTree. Eseguono aggiornamenti durante le fusioni in background. Puoi forzarlo usando optimize table. Ma non farlo troppo spesso, perch\u00e9 comporterebbe una completa riscrittura della partizione. <\/p>\n<p><\/p>\n<p>I JOIN distribuiti in ClickHouse sono anche poco gestiti dal pianificatore di query. <\/p>\n<p><\/p>\n<p>Male, ma a volte va bene.<\/p>\n<p><\/p>\n<p>Utilizzo di ClickHouse solo per leggere nuovamente i dati tramite select*.<\/p>\n<p><\/p>\n<p>Non consiglierei di usare ClickHouse per calcoli pesanti. Ma non \u00e8 proprio cos\u00ec, perch\u00e9 ci stiamo gi\u00e0 allontanando da questa raccomandazione. E recentemente \u00e8 stata aggiunta la possibilit\u00e0 di applicare modelli di machine learning in ClickHouse - Catboost. E questo mi preoccupa, perch\u00e9 penso: \u00abChe disastro. Quanti cicli per byte ci sono?!\u00bb. \u00c8 davvero un peccato sprecare cicli per byte. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilizzo efficace di ClickHouse. Aleksey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/f686d5d352ccb444cd06e2ae68897137.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ma non temete, installate ClickHouse, andr\u00e0 tutto bene. In caso di problemi, abbiamo una comunit\u00e0. A proposito, la comunit\u00e0 siete voi. E se avete qualche problema, potete almeno entrare nella nostra chat, e spero vi aiuteranno. <\/p>\n<p><\/p>\n<p>Domande<\/p>\n<p><\/p>\n<p><em>Grazie per la presentazione! Dove posso lamentarmi per il crash di ClickHouse?<\/em><\/p>\n<p><\/p>\n<p>Potete lamentarvi direttamente a me adesso. <\/p>\n<p><\/p>\n<p><em>Recentemente ho iniziato a usare ClickHouse. Ho subito fatto crashare l'interfaccia cli.<\/em><\/p>\n<p><\/p>\n<p>Sei fortunato. <\/p>\n<p><\/p>\n<p><em>Poco dopo ho crashato il server con una piccola select.<\/em><\/p>\n<p><\/p>\n<p>Hai talento. <\/p>\n<p><\/p>\n<p><em>Ho aperto un bug su GitHub, ma \u00e8 stato ignorato.<\/em> <\/p>\n<p><\/p>\n<p>Vedremo. <\/p>\n<p><\/p>\n<p><em>Aleksei mi ha ingannato facendomi venire alla presentazione, promettendo di raccontare come comprimete i dati internamente.<\/em><\/p>\n<p><\/p>\n<p>Molto semplice. <\/p>\n<p><\/p>\n<p><em>L'ho capito gi\u00e0 ieri. Serve pi\u00f9 concretezza.<\/em> <\/p>\n<p><\/p>\n<p>Non ci sono trucchi terribili. \u00c8 solo compressione per blocchi. Di default viene usato LZ4, puoi attivare ZSTD*. I blocchi vanno da 64 kilobyte a 1 megabyte.<\/p>\n<p><\/p>\n<p>* ci sono anche codec di compressione specializzati che possono essere utilizzati in catena con altri algoritmi.<\/p>\n<p><\/p>\n<p><em>Nei blocchi ci sono solo dati grezzi?<\/em><\/p>\n<p><\/p>\n<p>Non proprio grezzi. Ci sono degli array. Se hai una colonna numerica, i numeri sono memorizzati consecutivamente in un array. <\/p>\n<p><\/p>\n<p><em>Chiaro.<\/em> <\/p>\n<p><\/p>\n<p><em>Aleksei, l'esempio che avevamo con uniqExact sugli indirizzi IP, cio\u00e8, che uniqExact impiega pi\u00f9 tempo sui dati testuali che su quelli numerici e cos\u00ec via. E se applicassimo un trucco e facessimo il cast nel momento della lettura? Cio\u00e8, sembrava che dicessi che su disco non ci sono grandi differenze. Se leggiamo le stringhe dal disco, facciamo il cast, allora avremo aggregati pi\u00f9 rapidi o no? O comunque non guadagneremmo significativamente qui? Mi sembra che tu lo abbia testato, ma per qualche motivo non l'hai indicato nel benchmark.<\/em> <\/p>\n<p><\/p>\n<p>Penso che sar\u00e0 pi\u00f9 lento rispetto a senza il cast. In questo caso, l'indirizzo IP deve essere estratto dalla stringa. Certo, in ClickHouse anche il parsing degli indirizzi IP \u00e8 ottimizzato. Abbiamo fatto del nostro meglio, ma l\u00ec i numeri sono scritti in forma decimale. Molto scomodo. D'altra parte, la funzione uniqExact lavorer\u00e0 pi\u00f9 lentamente sulle stringhe non solo perch\u00e9 sono stringhe, ma anche perch\u00e9 viene scelta un'altra specializzazione dell'algoritmo. Le stringhe vengono semplicemente elaborate in modo diverso.<\/p>\n<p><\/p>\n<p><em>E se prendessimo un tipo di dato pi\u00f9 primitivo? Ad esempio, abbiamo registrato l'user id, che \u00e8 nel nostro in, l'abbiamo registrato come stringa e poi l'abbiamo castato, sar\u00e0 pi\u00f9 divertente o no?<\/em><\/p>\n<p><\/p>\n<p>Dubbio. Penso che sar\u00e0 persino pi\u00f9 triste, perch\u00e9 analizzare numeri \u00e8 un problema serio. Mi sembra che questo collega abbia persino tenuto una presentazione su quanto sia difficile analizzare i numeri in forma decimale, o forse no. <\/p>\n<p><\/p>\n<p><em>Alexey, grazie mille per la presentazione! E grazie mille anche per ClickHouse! Ho una domanda riguardo ai piani. Ci sono previsioni per una funzionalit\u00e0 di aggiornamento dei dizionari non completamente?<\/em><\/p>\n<p><\/p>\n<p>Cio\u00e8, un riavvio parziale?<\/p>\n<p><\/p>\n<p><em>S\u00ec, s\u00ec. Tipo la possibilit\u00e0 di indicare un campo MySQL, cio\u00e8 aggiornare dopo, affinch\u00e9 vengano caricati solo quei dati, se il dizionario \u00e8 molto grande.<\/em><\/p>\n<p><\/p>\n<p>Funzionalit\u00e0 molto interessante. E mi sembra che qualcuno l'abbia proposta nella nostra chat. Forse era anche tu. <\/p>\n<p><\/p>\n<p><em>Non credo di essere io.<\/em><\/p>\n<p><\/p>\n<p>Ottimo, ora risultano due richieste. E possiamo iniziare a farlo con calma. Ma voglio avvisarti subito che questa funzionalit\u00e0 \u00e8 piuttosto semplice da implementare. Cio\u00e8, in teoria, basta scrivere nella tabella il numero di versione e poi continuare a scrivere: versione inferiore a quello. E ci\u00f2 significa che, molto probabilmente, proporremo di farlo agli appassionati. Sei un appassionato? <\/p>\n<p><\/p>\n<p><em>S\u00ec, ma sfortunatamente non in C++.<\/em><\/p>\n<p><\/p>\n<p>I tuoi colleghi sanno scrivere in C++? <\/p>\n<p><\/p>\n<p><em>Trover\u00f2 qualcuno.<\/em><\/p>\n<p><\/p>\n<p>Ottimo*.<\/p>\n<p><\/p>\n<p>* la funzionalit\u00e0 \u00e8 stata aggiunta due mesi dopo la presentazione - \u00e8 stata sviluppata dall'autore della domanda e ha inviato la sua <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/ClickHouse\/ClickHouse\/pull\/1771\">pull request<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p><em>Grazie!<\/em><\/p>\n<p><\/p>\n<p><em>Ciao! Grazie per la presentazione! Hai menzionato che ClickHouse utilizza molto bene tutte le risorse disponibili. E il relatore vicino a Luxoft ha parlato della sua soluzione per Posta Russa. Ha detto che a loro \u00e8 piaciuto molto ClickHouse, ma non lo hanno usato al posto del loro principale concorrente proprio perch\u00e9 consumava tutta la CPU. E non sono riusciti a integrarlo nella loro architettura, nel loro ZooKeeper con i container Docker. \u00c8 possibile limitare ClickHouse in modo che non consumi tutto ci\u00f2 che diventa disponibile?<\/em><\/p>\n<p><\/p>\n<p>S\u00ec, \u00e8 possibile e molto facile. Se vuoi che utilizzi meno core, basta scrivere <code>set max_threads = 1<\/code>. E tutto, eseguir\u00e0 la query su un solo core. Inoltre, \u00e8 possibile impostare questa configurazione in modo diverso per utenti diversi. Quindi non ci sono problemi. E fai sapere ai tuoi colleghi di Luxoft che non \u00e8 corretto che non abbiano trovato questa impostazione nella documentazione. <\/p>\n<p><\/p>\n<p><em>Ciao Aleksej! Vorrei porre una domanda. Non \u00e8 la prima volta che sento dire che molti iniziano a utilizzare ClickHouse come archiviazione per i log. Nella presentazione hai detto di non farlo, cio\u00e8 non \u00e8 necessario memorizzare stringhe lunghe. Cosa ne pensi?<\/em><\/p>\n<p><\/p>\n<p>Innanzitutto, i log non sono, di regola, stringhe lunghe. Ci possono essere delle eccezioni. Ad esempio, un servizio scritto in Java lancia eccezioni, queste vengono registrate. E cos\u00ec in un ciclo infinito, e lo spazio sul disco finisce. La soluzione \u00e8 molto semplice. Se le stringhe sono molto lunghe, tagliale. E cosa significa 'lunghe'? Decine di kilobyte \u00e8 un problema*.<\/p>\n<p><\/p>\n<p>* nelle versioni recenti di ClickHouse \u00e8 stata introdotta la \"granularit\u00e0 adattiva dell'indice\", che risolve per la maggior parte il problema dello stoccaggio di lunghe stringhe.<\/p>\n<p><\/p>\n<p><em>E un kilobyte \u00e8 normale?<\/em><\/p>\n<p><\/p>\n<p>Normale. <\/p>\n<p><\/p>\n<p><em>Ciao! Grazie per la presentazione! Ho gi\u00e0 chiesto di questo in chat, ma non ricordo se ho ricevuto una risposta. \u00c8 previsto in qualche modo di ampliare la sezione WITH in stile CTE?<\/em><\/p>\n<p><\/p>\n<p>Per ora no. La sezione WITH da noi \u00e8 piuttosto superficiale. \u00c8 una piccola funzionalit\u00e0.<\/p>\n<p><\/p>\n<p><em>Ho capito. Grazie!<\/em><\/p>\n<p><\/p>\n<p><em>Grazie per la presentazione! Molto interessante! Domanda globale. \u00c8 previsto di fare, magari, in forma di qualche placeholder, una modifica per l'eliminazione dei dati?<\/em><\/p>\n<p><\/p>\n<p>Certamente. Questa \u00e8 la nostra priorit\u00e0 nella nostra lista di cose da fare. Stiamo attualmente pensando attivamente a come fare tutto nel modo giusto. E bisogna cominciare a digitare sulla tastiera*.<\/p>\n<p><\/p>\n<p>* hanno premuto i pulsanti sulla tastiera e hanno fatto tutto.<\/p>\n<p><\/p>\n<p><em>Questo influir\u00e0 in qualche modo sulle prestazioni del sistema o no? L'inserimento sar\u00e0 veloce come ora?<\/em><\/p>\n<p><\/p>\n<p>Forse le eliminazioni e gli aggiornamenti stessi saranno molto pesanti, ma ci\u00f2 non influir\u00e0 sulle prestazioni delle selezioni e sulle prestazioni degli inserimenti.<\/p>\n<p><\/p>\n<p><em>E un'ultima domanda. Nella presentazione hai parlato della chiave primaria. Di conseguenza, abbiamo una partizionamento, che per impostazione predefinita \u00e8 mensile, corretto? E quando impostiamo l'intervallo di date che rientra nel mese, viene letta solo quella partizione, giusto?<\/em><\/p>\n<p><\/p>\n<p>S\u00ec.<\/p>\n<p><\/p>\n<p><em>Una domanda. Se non possiamo identificare nessuna chiave primaria, \u00e8 corretto farla basare sul campo \"Data\" per ridurre la ristrutturazione di questi dati in background e ordinarli meglio? Se non hai richieste a intervalli e non riesci nemmeno a selezionare alcuna chiave primaria, ha senso inserire la data nella chiave primaria?<\/em><\/p>\n<p><\/p>\n<p>S\u00ec.<\/p>\n<p><\/p>\n<p>Forse ha senso inserire nella chiave primaria un campo che permetta una migliore compressione dei dati, se sono ordinati per quel campo. Ad esempio, l'identificativo dell'utente. Se un utente visita lo stesso sito. In questo caso, inserisci l'id dell'utente e il tempo. Cos\u00ec i tuoi dati si comprimeranno meglio. Per quanto riguarda la data, se non hai realmente richieste a intervalli sulle date e non le avrai mai, non \u00e8 necessario includere la data nella chiave primaria. <\/p>\n<p><\/p>\n<p><em>Va bene, grazie mille!<\/em><\/p>\n<p>Fonte: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/514840\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0422\u0430\u043a \u043a\u0430\u043a ClickHouse \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439, \u043f\u0440\u0438 \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0432\u0430\u0436\u043d\u043e \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u0435\u0433\u043e \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b. \u0412 \u044d\u0442\u043e\u043c \u0434\u043e\u043a\u043b\u0430\u0434\u0435 \u0410\u043b\u0435\u043a\u0441\u0435\u0439 \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0435\u0442 \u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445 \u0442\u0438\u043f\u0438\u0447\u043d\u044b\u0445 \u043e\u0448\u0438\u0431\u043e\u043a \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 ClickHouse, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043a \u043d\u0435\u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u0435. \u041d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445 \u0438\u0437 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0438 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043e, \u043a\u0430\u043a \u0432\u044b\u0431\u043e\u0440 \u0442\u043e\u0439 \u0438\u043b\u0438 \u0438\u043d\u043e\u0439 \u0441\u0445\u0435\u043c\u044b \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u043e\u0436\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043d\u0430 \u043f\u043e\u0440\u044f\u0434\u043a\u0438. \u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442! \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":91439,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-91438","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/effektivnoe-ispolzovanie-clickhouse-aleksej-milovidov-yandeks\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"it_IT\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u042d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 ClickHouse. \u0410\u043b\u0435\u043a\u0441\u0435\u0439 \u041c\u0438\u043b\u043e\u0432\u0438\u0434\u043e\u0432 (\u042f\u043d\u0434\u0435\u043a\u0441) | ProHoster\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/effektivnoe-ispolzovanie-clickhouse-aleksej-milovidov-yandeks\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-08-13T17:42:36+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-08-13T17:42:36+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Utilizzo efficace di ClickHouse. Aleksej Milovidov (Yandex) | ProHoster","description":"","canonical_url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/effektivnoe-ispolzovanie-clickhouse-aleksej-milovidov-yandeks","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"it_IT","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u042d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 ClickHouse. \u0410\u043b\u0435\u043a\u0441\u0435\u0439 \u041c\u0438\u043b\u043e\u0432\u0438\u0434\u043e\u0432 (\u042f\u043d\u0434\u0435\u043a\u0441) | ProHoster","og:url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/effektivnoe-ispolzovanie-clickhouse-aleksej-milovidov-yandeks","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-08-13T17:42:36+00:00","article:modified_time":"2020-08-13T17:42:36+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"91438","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 12:27:23","updated":"2022-09-28 17:25:41","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/91438","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/comments?post=91438"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/91438\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media\/91439"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=91438"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=91438"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=91438"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}