{"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":"Uso efficace di ClickHouse. Alexey Milovidov (Yandex)","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey 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 tenere a mente le peculiarit\u00e0 della sua architettura durante il suo utilizzo. In questa presentazione, Aleksey parler\u00e0 di esempi comuni di errori nell'uso di ClickHouse che possono portare a prestazioni inefficaci. Attraverso esempi pratici, verr\u00e0 mostrato come la scelta di un particolare schema di elaborazione dei dati possa influenzare le prestazioni in modo significativo.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Ciao a tutti! Mi chiamo Aleksey e mi occupo di ClickHouse.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/7f5fc01663be58d3d25e518a4169b8cf.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Innanzitutto, voglio subito rassicurarvi: oggi non vi parler\u00f2 di cosa sia ClickHouse. Onestamente, mi ha stancato. Ogni volta ripeto la stessa cosa, e probabilmente tutti gi\u00e0 lo sanno. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey 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 delle possibili insidie, ovvero di come si possa utilizzare ClickHouse in modo errato. In realt\u00e0, non c'\u00e8 motivo di preoccuparsi, poich\u00e9 sviluppiamo ClickHouse come un sistema semplice, comodo e funzionante 'out of the box'. \u00c8 sufficiente installarlo e il gioco \u00e8 fatto, senza problemi. <\/p>\n<p><\/p>\n<p>Tuttavia, \u00e8 importante considerare che questo \u00e8 un sistema specializzato e si pu\u00f2 facilmente imbattersi in scenari di utilizzo insoliti che potrebbero portare il sistema fuori dalla sua zona di comfort.<\/p>\n<p><\/p>\n<p>Quindi, quali sono i problemi? Principalmente parler\u00f2 delle cose ovvie. \u00c8 evidente per tutti, tutti capiscono e possono essere contenti di essere cos\u00ec intelligenti, mentre chi non capisce, scoprir\u00e0 qualcosa di nuovo. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey 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 semplice, che purtroppo si verifica spesso, \u00e8 un gran numero di inserti con piccoli batch, ossia un gran numero di piccoli inserti.<\/p>\n<p><\/p>\n<p>Se consideriamo come ClickHouse esegue gli insert, puoi inviare un flusso di dati di un terabyte con una sola richiesta. Non \u00e8 un problema. <\/p>\n<p><\/p>\n<p>E diamo un'occhiata a quale sar\u00e0 una tipica prestazione. Ad esempio, abbiamo una tabella con dati da Yandex.Metrica. Hit. 105 colonne. 700 byte in forma non compressa. E inseriamo in modo appropriato batch di un milione di righe. <\/p>\n<p><\/p>\n<p>Inseriamo nella tabella MergeTree, otteniamo mezzo milione di righe al secondo. Ottimo. Nella tabella replicata \u2013 sar\u00e0 un po' meno, circa 400.000 righe al secondo. <\/p>\n<p><\/p>\n<p>E se attiviamo l'inserimento con quorum, otteniamo un po' meno, ma comunque una prestazione decente, 250.000 righe al secondo. L'inserimento con quorum \u00e8 una funzione non documentata in ClickHouse*.<\/p>\n<p><\/p>\n<p>* a partire dal 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=\"Uso efficace di ClickHouse. Alexey 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 lavora male? Inserendo una riga alla volta nella tabella MergeTree, otteniamo 59 righe al secondo. Questo \u00e8 10.000 volte pi\u00f9 lento. In ReplicatedMergeTree \u2013 6 righe al secondo. E se poi si attiva anche il quorum, si arriva a 2 righe al secondo. A mio avviso, \u00e8 una situazione inaccettabile. Come pu\u00f2 essere cos\u00ec lento? Ho persino una maglietta con scritto che ClickHouse non dovrebbe rallentare. Tuttavia, a volte succede. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey 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 una nostra mancanza. Avremmo potuto far funzionare tutto correttamente, ma non l'abbiamo fatto. E non l'abbiamo fatto perch\u00e9 per il nostro scenario non era necessario. Avevamo gi\u00e0 dei batch. I batch arrivavano a noi e tutto funzionava bene. Ma, naturalmente, possono esserci vari scenari. Ad esempio, quando hai un sacco di server su cui vengono generati dati. E questi inseriscono dati non cos\u00ec frequentemente, ma comunque ci sono inserimenti frequenti. E bisogna trovare un modo per evitarlo. <\/p>\n<p><\/p>\n<p>Dal punto di vista tecnico, la questione \u00e8 che quando si esegue un inserimento in ClickHouse, i dati non vengono memorizzati in nessun memtable. Non abbiamo nemmeno un vero log structure MergeTree, ma semplicemente un MergeTree, poich\u00e9 non ci sono log o memTable. I dati vengono scritti direttamente nel file system, gi\u00e0 organizzati per colonne. E se avete 100 colonne, dovrete scrivere pi\u00f9 di 200 file in una directory separata. Tutto ci\u00f2 \u00e8 piuttosto ingombrante. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey 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 procedere correttamente?\u00bb, se ci si trova nella situazione di dover comunque scrivere dati in ClickHouse.<\/p>\n<p><\/p>\n<p>Metodo 1. Questo \u00e8 il metodo pi\u00f9 semplice. Utilizzare un sistema di coda distribuito, come Kafka. Si estraggono semplicemente i dati da Kafka e si esegue un batch ogni secondo. E il tutto funzioner\u00e0 correttamente, registrate e tutto proceder\u00e0 senza problemi. <\/p>\n<p><\/p>\n<p>I difetti sono che Kafka \u00e8 un'altra ingombrante sistema distribuito. Capisco se nella vostra azienda gi\u00e0 avete Kafka. \u00c8 un bene, \u00e8 conveniente. Ma se non lo avete, allora vale la pena riflettere pi\u00f9 volte prima di introdurre un'altra piattaforma distribuita nel vostro progetto. Pertanto, \u00e8 opportuno considerare delle alternative. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/4f687221e8c7443abf02fb002c4eba5b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Metodo 2. Un'alternativa old-school piuttosto semplice. Avete un server che genera i vostri log. Questo server scrive semplicemente i log in un file. E ogni secondo, per esempio, rinominiamo quel file e ne apriamo uno nuovo. Un secondo script, sia tramite cron che come daemon, prende il file pi\u00f9 vecchio e lo scrive in ClickHouse. Se scrivete i log ogni secondo, tutto funzioner\u00e0 a meraviglia. <\/p>\n<p><\/p>\n<p>Ma il difetto di questo metodo \u00e8 che se il server che genera i log scompare, anche i dati scompariranno.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey 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 metodo interessante che non utilizza file temporanei. Ad esempio, avete un qualche tipo di sistema di pubblicit\u00e0 o un daemon interessante che genera dati. Potete accumulare un certo numero di dati direttamente nella RAM, nel buffer. E quando \u00e8 passato un determinato periodo di tempo, mettete quel buffer da parte, ne create uno nuovo e in un thread separato inserite ci\u00f2 che avete accumulato in ClickHouse.<\/p>\n<p><\/p>\n<p>D'altra parte, i dati scompaiono anche con il kill -9. Se il tuo server si arresta, perderai questi dati. Inoltre, c'\u00e8 il problema che, se non sei riuscito a scrivere nel database, i dati si accumuleranno nella RAM. E o finir\u00e0 la RAM o semplicemente perderai i dati. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey 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 processo server. E pu\u00f2 inviare dati a ClickHouse immediatamente, ma farlo in un'unica connessione. Ad esempio, invia una richiesta http con transfer-encoding: chunked con insert. E genera 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 subito. E ClickHouse li bufferizzer\u00e0 da solo. <\/p>\n<p><\/p>\n<p>Ma sorgono anche problemi. Ora perderai dati, in particolare quando il tuo processo si arresta e, se il processo ClickHouse si arresta, perch\u00e9 sar\u00e0 un insert incompleto. In ClickHouse gli insert sono atomici fino a una certa soglia specificata in numero di righe. In linea di principio, \u00e8 un modo interessante. Anche questo pu\u00f2 essere usato.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey 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 interessante approccio. Si tratta di un server sviluppato dalla community per l'elaborazione batch dei dati. Non l'ho esaminato personalmente, quindi non posso garantire nulla. Tuttavia, nemmeno per ClickHouse vengono fornite garanzie. Anche questo \u00e8 open source, ma dall'altra parte, potreste essere abituati a determinati standard di qualit\u00e0 che ci impegniamo a garantire. Per questa soluzione, non lo so, andate su GitHub e guardate il codice. Potrebbe essere che abbiano scritto qualcosa di valido. <\/p>\n<p><\/p>\n<p>* a partire dal 2020, si dovrebbe anche 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=\"Uso efficace di ClickHouse. Alexey 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 modo \u00e8 utilizzare le tabelle Buffer. I vantaggi di questo metodo sono che \u00e8 molto semplice da iniziare a usare. Crei una tabella Buffer e ci inserisci i dati. <\/p>\n<p><\/p>\n<p>E il problema \u00e8 che non viene risolto completamente. Se nella scrittura di tipo MergeTree devi raggruppare i dati in un solo batch al secondo, quando scrivi in una tabella buffer, devi raggruppare almeno fino a diverse migliaia al secondo. Se supera le 10.000 al secondo, sar\u00e0 comunque problematico. E se si inseriscono batch, hai visto che si arriva a centinaia di migliaia di righe al secondo. E questo \u00e8 gi\u00e0 su dati piuttosto pesanti. <\/p>\n<p><\/p>\n<p>E anche le tabelle buffer non hanno 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=\"Uso efficace di ClickHouse. Alexey 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 abbiamo introdotto la possibilit\u00e0 di prelevare dati da Kafka. Esiste un motore di tabelle \u2013 Kafka. Basta crearne uno. E su di esso \u00e8 possibile agganciare viste materializzate. In questo caso, estrarr\u00e0 autonomamente i dati da Kafka e li inserir\u00e0 nelle tabelle desiderate. <\/p>\n<p><\/p>\n<p>E ci\u00f2 che \u00e8 particolarmente gratificante di questa possibilit\u00e0 \u00e8 che non l'abbiamo realizzata noi. \u00c8 una funzionalit\u00e0 della community. E quando dico \"funzionalit\u00e0 della community\", lo dico senza alcun disprezzo. Abbiamo esaminato il codice, abbiamo fatto le revisioni, dovrebbe funzionare correttamente. <\/p>\n<p><\/p>\n<p>* alla fine del 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=\"Uso efficace di ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/15dc61dfd435f5f8640395b7de480fe2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Cosa potrebbe essere scomodo o inaspettato quando si inseriscono dati? Se si esegue una query insert values e in values si scrivono delle espressioni calcolate. Ad esempio, now() \u00e8 un'espressione calcolata. In questo caso, ClickHouse deve avviare l'interprete di queste espressioni per ogni riga, e le prestazioni ne risentono notevolmente. \u00c8 meglio evitarlo.<\/p>\n<p><\/p>\n<p>* Al momento, il problema \u00e8 completamente risolto, non ci sono pi\u00f9 regressioni delle prestazioni nell'uso delle espressioni in VALUES.<\/p>\n<p><\/p>\n<p>Un altro esempio di potenziali problemi si verifica quando i dati di un singolo batch appartengono a molteplici partizioni. Per impostazione predefinita, in ClickHouse le partizioni sono mensili. Se si inserisce un batch di un milione di righe e queste riguardano un arco di diversi anni, si trover\u00e0 ad avere decine di partizioni. Questo equivale a batch di dimensioni significativamente pi\u00f9 piccole, poich\u00e9 all'interno vengono sempre suddivisi per partizioni.<\/p>\n<p><\/p>\n<p>* Recentemente, ClickHouse ha aggiunto in modalit\u00e0 sperimentale il supporto per il formato compatto di parti e parti in memoria con write-ahead log, il che risolve quasi completamente il problema.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/b8c6cecdba53559dad31ed11713a980d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ora esaminiamo il secondo tipo di problema: la tipizzazione dei dati. <\/p>\n<p><\/p>\n<p>La tipizzazione dei dati pu\u00f2 essere stretta o basata su stringhe. La tipizzazione basata su stringhe \u00e8 quando hai semplicemente dichiarato che tutti i tuoi campi sono di tipo string. \u00c8 una cattiva pratica. Non dovresti farlo. <\/p>\n<p><\/p>\n<p>Vediamo come fare correttamente nei casi in cui vogliamo indicare che un certo campo \u00e8 una stringa, lasciando a ClickHouse il compito di gestirlo, senza preoccuparci troppo. Tuttavia, vale la pena fare alcuni sforzi. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey 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 una stringa, per esempio, 192.168.1.1. Nell'altro caso, sar\u00e0 un numero di tipo UInt32*. 32 bit sono sufficienti per un indirizzo IPv4.<\/p>\n<p><\/p>\n<p>Prima di tutto, sorprendentemente, i dati verranno compressi in modo simile. Ci sar\u00e0 una certa differenza, ovviamente, ma non cos\u00ec grande. Quindi non ci sono problemi particolari con l'input\/output del disco. <\/p>\n<p><\/p>\n<p>Ma c'\u00e8 una differenza significativa in termini di tempo di elaborazione della CPU e di tempo di esecuzione della query. <\/p>\n<p><\/p>\n<p>Calcoliamo il numero di indirizzi IP unici se memorizzati sotto forma di numeri. Si ottengono 137 milioni di righe al secondo. Se invece sono memorizzati come stringhe, si ottengono 37 milioni di righe al secondo. Non so perch\u00e9 ci sia questa coincidenza. Ho eseguito personalmente queste query. Tuttavia, \u00e8 circa quattro volte pi\u00f9 lento. <\/p>\n<p><\/p>\n<p>Se consideriamo la differenza nello spazio su disco, c'\u00e8 anche una variazione. La differenza \u00e8 di circa un quarto, poich\u00e9 ci sono molti indirizzi IP unici. Se qui ci fossero righe con un numero ridotto di valori diversi, esse si comprimerebbero facilmente secondo un dizionario, mantenendo un volume simile. <\/p>\n<p><\/p>\n<p>Una differenza quadrupla nel tempo non \u00e8 da trascurare. Forse a voi non importa, ma quando vedo una differenza simile, mi rende triste.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/f74dbfdab5a9e26fa044a5870a8cc00d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Esaminiamo diversi casi. <\/p>\n<p><\/p>\n<p>1. Un caso in cui avete pochi valori unici diversi. In questo caso, utilizziamo una pratica semplice che probabilmente conoscete e potete applicare a qualsiasi DBMS. Questo ha senso non solo per ClickHouse. \u00c8 sufficiente memorizzare nella base dati identificatori numerici. La conversione in stringhe e viceversa pu\u00f2 avvenire sul lato della vostra applicazione. <\/p>\n<p><\/p>\n<p>Ad esempio, avete una regione e cercate di salvarla come stringa. Risultato: Mosca e MO. Quando vedo 'Mosca', penso che vada bene, ma quando appare anche MO, mi sembra davvero triste. Quanti byte sono? <\/p>\n<p><\/p>\n<p>Invece, salviamo semplicemente il numero Ulnt32 e 250. Abbiamo 250 in Yandex, ma potrebbe essere diverso da voi. A scanso di equivoci, vorrei sottolineare che ClickHouse ha una funzionalit\u00e0 integrata per lavorare con le geodatabase. Basta registrare un elenco con le regioni, incluso quello gerarchico, cio\u00e8 ci sar\u00e0 sia Mosca che MO, e tutto ci\u00f2 di cui hai bisogno. E puoi convertire a livello di query. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/cc6e871136dab8f8a35246a5af512cda.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Il secondo approccio \u00e8 simile, ma gi\u00e0 con supporto all'interno di ClickHouse. \u00c8 il tipo di dato Enum. All'interno di Enum si definiscono tutti i valori necessari. Ad esempio, il tipo di dispositivo e poi scrivi: desktop, mobile, tablet, televisore. Solo 4 varianti. <\/p>\n<p><\/p>\n<p>Il problema \u00e8 che \u00e8 necessario alternare periodicamente. \u00c8 stato aggiunto solo un'opzione. Facciamo un alter table. In realt\u00e0, l'alter table in ClickHouse \u00e8 gratuito. \u00c8 particolarmente gratuito per Enum, poich\u00e9 i dati su disco non cambiano. Tuttavia, l'alter acquisisce un blocco sulla tabella e deve attendere che tutte le selezioni siano completate. Solo dopo l'alter verr\u00e0 eseguito, cio\u00e8 ci sono comunque alcuni inconvenienti.<\/p>\n<p><\/p>\n<p>* nelle versioni recenti di ClickHouse, l'ALTER \u00e8 stato completamente non bloccante.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey 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 piuttosto unica per ClickHouse \u00e8 la connessione di dizionari esterni. Puoi scrivere numeri in ClickHouse e mantenere i tuoi dizionari in qualsiasi sistema ti sia comodo. Ad esempio, puoi utilizzare: MySQL, Mongo, Postgres. Puoi persino creare il tuo microservizio che fornisce questi dati tramite http. E a livello di ClickHouse scrivi una funzione che trasforma 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 di queste, i dati saranno completamente memorizzati nella cache, presenti interamente in memoria e aggiornati con una certa periodicit\u00e0. Nell'altra variante, se i dati non possono essere caricati in memoria, \u00e8 possibile memorizzarli parzialmente nella cache. <\/p>\n<p><\/p>\n<p>Ecco un esempio. C'\u00e8 Yandex.Direct. L\u00ec ci sono campagne pubblicitarie e banner. Ci sono probabilmente circa dieci milioni di campagne pubblicitarie. E pi\u00f9 o meno si adattano in memoria. Ma ci sono miliardi di banner che non ci stanno. E utilizziamo un dizionario memorizzato nella cache da MySQL.<\/p>\n<p><\/p>\n<p>L'unico problema \u00e8 che il dizionario memorizzato nella cache funzioner\u00e0 bene solo se il tasso di hit \u00e8 vicino al 100%. Se \u00e8 inferiore, per l'elaborazione delle richieste di ogni blocco di dati sar\u00e0 necessario recuperare effettivamente le chiavi mancanti e raccogliere i dati da MySQL. Per quanto riguarda ClickHouse, posso garantire che non rallenta, ma non parler\u00f2 di altri sistemi.<\/p>\n<p><\/p>\n<p>Come bonus, i dizionari sono un modo molto semplice per aggiornare retrospettivamente i dati in ClickHouse. Ovvero, se avevate un report sulle campagne pubblicitarie, un utente pu\u00f2 semplicemente cambiare la campagna pubblicitaria e tutti i dati vecchi, in tutti i report, verranno aggiornati. Se scrivete direttamente nelle righe della tabella, non sar\u00e0 possibile aggiornarle. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey 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, quando non sapete da dove prendere gli identificatori per le vostre righe, \u00e8 semplicemente fare un hash. La soluzione 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, ci saranno quasi sicuramente delle collisioni. Perch\u00e9 se ci sono miliardi di righe, la probabilit\u00e0 diventa significativa. <\/p>\n<p><\/p>\n<p>E non sarebbe una buona idea fare cos\u00ec per hashare i nomi delle campagne pubblicitarie. Se le campagne pubblicitarie di aziende diverse si confondono, il risultato sar\u00e0 incomprensibile. <\/p>\n<p><\/p>\n<p>C'\u00e8 un trucco semplice. Certo, non \u00e8 molto adatto per dati seri, ma se non sono cos\u00ec critici, basta aggiungere l'identificatore del cliente alla chiave del dizionario. In questo modo, ci saranno collisioni, ma solo all'interno di un singolo cliente. Questo metodo \u00e8 utilizzato per la mappa dei link in Yandex.Metrica. Abbiamo degli URL l\u00ec, memorizziamo gli hash. E sappiamo che ci sono collisioni, ovviamente. Ma quando la pagina viene visualizzata, la probabilit\u00e0 che su una stessa pagina un utente abbia degli URL sovrapposti che vengano notati \u00e8 cos\u00ec bassa che si pu\u00f2 trascurare. <\/p>\n<p><\/p>\n<p>Come bonus, per molte operazioni \u00e8 sufficiente avere solo gli hash e non \u00e8 necessario memorizzare le stringhe in nessun altro posto. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey 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, se le stringhe sono brevi, come i domini dei siti. Possono essere memorizzate cos\u00ec come sono. Oppure, ad esempio, la lingua del browser ru - 2 byte. Certo, dispiace un po' per i byte, ma non preoccuparti, 2 byte non sono un problema. Per favore, memorizza cos\u00ec come sono, non complicarti la vita. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/901eaed0029da6ea59630b57ccf80c25.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Un altro caso in cui, al contrario, ci sono molte stringhe e in esse molte uniche, e in pi\u00f9 con un numero potenzialmente illimitato. 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 sono quasi la met\u00e0 di tutti gli eventi. E in questo caso potresti pensare di normalizzare i dati, contare gli identificatori e metterli in una tabella separata. Ma non \u00e8 necessario farlo. Basta conservare queste stringhe cos\u00ec come sono. <\/p>\n<p><\/p>\n<p>\u00c8 meglio \u2013 non inventare nulla, perch\u00e9 se conservi separatamente, sar\u00e0 necessario fare un join. E questo join \u2013 nel migliore dei casi \u00e8 accesso casuale in memoria, se ci sta dentro. Se non ci sta, ci saranno problemi. <\/p>\n<p><\/p>\n<p>E se i dati sono memorizzati in loco, vengono semplicemente letti nell'ordine corretto dal file system e tutto funziona bene.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey 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 complessa e lunga, dovresti considerare che puoi calcolare un riassunto in anticipo e registrarlo in una colonna separata. <\/p>\n<p><\/p>\n<p>Per gli URL, ad esempio, \u00e8 possibile memorizzare separatamente il dominio. E se hai veramente bisogno di un dominio, utilizza semplicemente questa colonna, mentre gli URL saranno conservati e non dovrai neppure toccarli. <\/p>\n<p><\/p>\n<p>Vediamo quale pu\u00f2 essere la differenza. In ClickHouse c'\u00e8 una funzione specializzata che calcola il dominio. \u00c8 molto veloce, l'abbiamo ottimizzata. E, a essere onesti, non rispetta nemmeno gli RFC, ma per il resto calcola tutto ci\u00f2 che ci serve. <\/p>\n<p><\/p>\n<p>In un caso, estrarremo semplicemente gli URL e calcoleremo il dominio. Questo richiede 166 millisecondi. Se invece prendiamo un dominio gi\u00e0 pronto, impieghiamo solo 67 millisecondi, cio\u00e8 quasi tre volte pi\u00f9 veloce. E non \u00e8 che abbiamo bisogno di fare calcoli complessi, ma semplicemente leggiamo meno dati. <\/p>\n<p><\/p>\n<p>Per qualche motivo, una delle query che \u00e8 pi\u00f9 lenta ha una velocit\u00e0 di trasferimento dei gigabyte al secondo superiore. Perch\u00e9 legge pi\u00f9 gigabyte. Questi dati sono completamente superflui. La query sembra funzionare pi\u00f9 velocemente, ma ci mette pi\u00f9 tempo a completarsi.<\/p>\n<p><\/p>\n<p>Se si osserva la quantit\u00e0 di dati su disco, si pu\u00f2 vedere che l'URL \u00e8 di 126 megabyte, mentre il dominio \u00e8 solo di 5 megabyte. Quindi \u00e8 25 volte meno. Tuttavia, la richiesta viene eseguita solo 4 volte pi\u00f9 velocemente. Questo perch\u00e9 i dati sono caldi. Se fossero stati freddi, probabilmente sarebbe stato 25 volte pi\u00f9 veloce a causa dell'input-output del disco. <\/p>\n<p><\/p>\n<p>A proposito, se si valuta quanto il dominio sia pi\u00f9 piccolo dell'URL, risulta essere circa 4 volte. Eppure, i dati su disco occupano 25 volte meno spazio. Perch\u00e9? A causa della compressione. Sia l'URL che il dominio vengono compressi. Ma spesso l'URL contiene un sacco di spazzatura. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/c93d2128a41561ed7abb25d77414bc2d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Naturalmente, \u00e8 importante utilizzare i tipi di dati corretti, che sono progettati specificamente per i valori necessari o che sono adatti. Se siete in IPv4, memorizzate come UInt32*. Se siete in IPv6, allora FixedString(16), perch\u00e9 l'indirizzo IPv6 \u00e8 di 128 bit, cio\u00e8 memorizzatelo direttamente in formato binario. <\/p>\n<p><\/p>\n<p>E cosa fare se a volte avete indirizzi IPv4 e altre volte IPv6? S\u00ec, potete memorizzare entrambi. Una colonna per IPv4, l'altra per IPv6. Certamente, esiste la possibilit\u00e0 di mappare IPv4 in IPv6. Questo funzioner\u00e0, ma se avete bisogno spesso dell'indirizzo IPv4 nelle vostre richieste, sarebbe meglio 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=\"Uso efficace di ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/d7d6342ebd6b8b4f3526b3cd8a06cf26.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00c8 anche importante notare che \u00e8 consigliabile preprocessare i dati in anticipo. Ad esempio, se ricevete dei log grezzi. Potrebbe sembrare allettante inserire tutto direttamente in ClickHouse senza fare nulla, ma \u00e8 comunque opportuno eseguire i calcoli necessari.<\/p>\n<p><\/p>\n<p>Prendiamo ad esempio la versione del browser. In un certo reparto vicino, al quale non voglio puntare il dito, la versione del browser viene memorizzata in questo modo, cio\u00e8 come stringa: 12.3. E poi, per generare un rapporto, dividono questa stringa per un array, e prendono poi il primo elemento dell'array. Naturalmente, tutto rallenta. Ho chiesto perch\u00e9 stessero facendo in questo modo. Mi hanno risposto che non amano l'ottimizzazione prematura. E io non amo la pessimizzazione prematura.<\/p>\n<p><\/p>\n<p>In questo caso, sarebbe pi\u00f9 corretto separare in 4 colonne. Non abbiate paura, perch\u00e9 questo \u00e8 ClickHouse. ClickHouse \u00e8 un database a colonne. E pi\u00f9 piccole colonne ordinate ci sono, meglio \u00e8. Se avrete 5 BrowserVersion, fate 5 colonne. \u00c8 normale. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/f9a67221bf8508933d7bd336b16f9e04.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ora consideriamo cosa fare se hai molte stringhe molto lunghe o array molto lunghi. Non \u00e8 necessario memorizzarli in ClickHouse. Puoi invece salvare in ClickHouse solo un identificatore. E per queste stringhe lunghe, puoi conservarle in un altro sistema. <\/p>\n<p><\/p>\n<p>Ad esempio, in uno dei nostri servizi analitici ci sono alcuni parametri di eventi. E se sugli eventi arrivano molti parametri, noi salviamo semplicemente i primi 512 che incontriamo. Perch\u00e9 512 non \u00e8 un problema. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/755271e8788ba4bd638f493bf320c820.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Se non sei sicuro dei tuoi tipi di dati, puoi anche registrare i dati in ClickHouse, ma in una tabella temporanea di tipo Log, progettata per i dati temporanei. Dopodich\u00e9, puoi analizzare la distribuzione dei valori, vedere cosa hai e definire i tipi corretti.<\/p>\n<p><\/p>\n<p>* ora in ClickHouse c'\u00e8 il tipo di dati <noindex><a rel=\"nofollow\" href=\"https:\/\/clickhouse.tech\/docs\/en\/sql-reference\/data-types\/lowcardinality\/\">LowCardinality<\/a><\/noindex> che consente di memorizzare efficacemente le stringhe con minori oneri operativi.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/7e9e53d86a4189783c28ce56a669198c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ora consideriamo un altro caso interessante. A volte le cose funzionano in modo strano per alcune persone. Entro e vedo questo. E mi immagino subito che sia stato fatto da un amministratore molto esperto e intelligente, con una vasta esperienza nella configurazione di MySQL versione 3.23. <\/p>\n<p><\/p>\n<p>Qui vediamo mille tabelle, ognuna delle quali contiene un resto di una divisione di qualcosa di incomprensibile per mille. <\/p>\n<p><\/p>\n<p>In linea di principio, rispetto l'esperienza altrui e comprendo anche quanto possa essere stata sofferta questa esperienza. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/3a5e21ef2076966fcc627670485c5b3a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>E le ragioni sono pi\u00f9 o meno chiare. Sono stereotipi vecchi che possono essersi accumulati lavorando con altri sistemi. Ad esempio, nelle tabelle MyISAM non esiste una chiave primaria cluster. E questo modo di suddividere i dati potrebbe essere un tentativo disperato di ottenere la stessa funzionalit\u00e0. <\/p>\n<p><\/p>\n<p>Un'altra ragione \u00e8 che eseguire operazioni come alter su tabelle grandi \u00e8 complicato. Tutto verr\u00e0 bloccato. Anche se nelle versioni moderne di MySQL questo problema non \u00e8 pi\u00f9 cos\u00ec serio. <\/p>\n<p><\/p>\n<p>Oppure, ad esempio, il microsharding, ma ne parleremo tra poco.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey 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 fare cos\u00ec, perch\u00e9, in primo luogo, la chiave primaria \u00e8 cluster e i dati sono ordinati in base alla chiave primaria. <\/p>\n<p><\/p>\n<p>A volte mi chiedono: \u00abCome cambia la performance delle query di intervallo in ClickHouse in base alle dimensioni della tabella?\u00bb. Rispondo che non cambia affatto. Ad esempio, se avete una tabella con un miliardo di righe e leggete un intervallo di un milione di righe, va tutto bene. Se nella tabella ci sono un trilione di righe e leggete un milione di righe, sar\u00e0 praticamente lo stesso. <\/p>\n<p><\/p>\n<p>In secondo luogo, non servono cose come le partizioni manuali. Se andate a vedere cosa c'\u00e8 nel file system, noterete che la tabella \u00e8 un elemento piuttosto robusto. All'interno ci sono strutture simili a partizioni. Cio\u00e8, ClickHouse fa tutto per voi e non dovete preoccuparvi.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey 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 alterare colonne aggiungendo\/rimuovendo. <\/p>\n<p><\/p>\n<p>E non ha senso creare tabelle piccole, perch\u00e9 se avete dieci righe o diecimila righe nella tabella, non fa alcuna differenza. ClickHouse \u00e8 un sistema che ottimizza il throughput, non la latenza, quindi elaborare dieci righe non ha senso. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/144144b4740e9c5daec80c8dadc445f9.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00c8 meglio utilizzare una grande tabella. Liberatevi dei vecchi stereotipi, andr\u00e0 tutto bene. <\/p>\n<p><\/p>\n<p>Come bonus, nella nostra ultima versione \u00e8 stata introdotta la possibilit\u00e0 di creare una chiave di partizionamento personalizzata per eseguire varie operazioni di manutenzione su singole partizioni. <\/p>\n<p><\/p>\n<p>Ad esempio, potresti avere molte piccole tabelle, magari quando hai bisogno di elaborare dei dati intermedi. Ricevi dei chunk e devi eseguire una trasformazione su di essi prima di scriverli nella tabella finale. Per questo caso esiste un ottimo motore di tabella: StripeLog. \u00c8 simile a TinyLog, solo 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=\"Uso efficace di ClickHouse. Alexey 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 micro-sharding. Ad esempio, hai bisogno di sharding per i dati e hai 5 server, ma domani ne avrai 6. Ti chiedi come riequilibrare questi dati. E invece di suddividerli in 5 shard, ne crei 1.000. E poi assegni ciascuno di questi micro-shard a un server separato. Cos\u00ec, su un server, ad esempio, avrai 200 ClickHouse, con istanze separate su porte diverse o diversi database. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey 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 \u00e8 molto efficace. Questo perch\u00e9 anche un solo instance di ClickHouse cerca di utilizzare tutte le risorse disponibili del server per elaborare una singola richiesta. Ad esempio, se hai un server con 56 core di CPU, eseguendo una richiesta che impiega un secondo, utilizzer\u00e0 tutti e 56 i core. Se hai 200 ClickHouse su un unico server, avrai 10.000 thread attivi. In generale, le prestazioni ne risentiranno notevolmente.<\/p>\n<p><\/p>\n<p>Un'altra ragione \u00e8 che la distribuzione del lavoro tra questi instances sar\u00e0 disomogenea. Alcuni termineranno prima, altri dopo. Se tutto avvenisse all'interno di un unico instance, ClickHouse sarebbe in grado di gestire correttamente la distribuzione dei dati tra i thread. <\/p>\n<p><\/p>\n<p>Un'ulteriore ragione \u00e8 che si verificher\u00e0 interazione tra i processi tramite TCP. I dati dovranno essere serializzati e deserializzati e questo comporta un numero enorme di micro-shard. Questo metodo risulta semplicemente inefficiente.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey 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 definirlo tale, \u00e8 la presenza di un numero elevato di pre-aggregazioni.<\/p>\n<p><\/p>\n<p>In generale, la preaggregazione \u00e8 utile. Se avevate un miliardo di righe e le avete aggregate a 1.000 righe, ora la query si esegue istantaneamente. Tutto fantastico. \u00c8 possibile farlo. A tal fine, anche in ClickHouse esiste un tipo di tabella chiamato AggregatingMergeTree, che esegue l'aggregazione incrementale durante l'inserimento dei dati. <\/p>\n<p><\/p>\n<p>Tuttavia, ci sono casi in cui si pensa di aggregare i dati in un modo, e poi in un altro dipartimento, purtroppo non voglio dire quale, utilizzano tabelle SummingMergeTree per la somma in base alla chiave primaria, usando come chiave primaria circa 20 colonne diverse. Per ragioni di riservatezza, ho cambiato i nomi di alcune colonne, ma l'idea \u00e8 proprio quella.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/54e3a02ab4bbce7c63ded595780ae1f6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>E sorgono problemi. In primo luogo, la quantit\u00e0 di dati non diminuisce di molto. Ad esempio, potrebbe ridursi di tre volte. Tre volte sarebbe un buon compromesso per concedersi opportunit\u00e0 illimitate nell'analisi, che si ottengono se i dati non sono aggregati. Se i dati sono aggregati, invece di analisi si ottiene solo una misera statistica. <\/p>\n<p><\/p>\n<p>E cosa infastidisce di pi\u00f9? Il fatto che queste persone del dipartimento vicino camminano e a volte chiedono di aggiungere un'altra colonna alla chiave primaria. Cio\u00e8, abbiamo aggregato i dati in questo modo, e ora vogliamo qualcosa di pi\u00f9. Ma in ClickHouse non esiste il comando alter per la chiave primaria. Quindi bisogna scrivere qualche script in C++. E non mi piacciono gli script, anche se sono in C++.<\/p>\n<p><\/p>\n<p>E se si guarda a cosa \u00e8 stato creato ClickHouse, i dati non aggregati sono proprio lo scenario per cui \u00e8 nato. Se usi ClickHouse per dati non aggregati, stai facendo tutto correttamente. Se stai aggregando, allora a volte \u00e8 giustificabile. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey 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 entro in un server di produzione e guardo la lista dei processi. E ogni volta scopro che sta succedendo qualcosa di terribile. <\/p>\n<p><\/p>\n<p>Ad esempio, qualcosa del genere. Qui \u00e8 subito chiaro che tutto poteva essere eseguito in una sola query. Basta scrivere l\u00ec url in e la lista.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/ae03b659f178962f50e0640614517296.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Perch\u00e9 ci sono molte richieste in un ciclo infinito - \u00e8 un problema? Se l'indice non viene utilizzato, avrai molte passate sugli stessi dati. Ma se l'indice viene utilizzato, ad esempio, hai una chiave primaria su ru e scrivi url = qualcosa. E pensi che verr\u00e0 letta in modo mirato una sola url dalla tabella, va tutto bene. Ma in realt\u00e0 non \u00e8 cos\u00ec. Perch\u00e9 ClickHouse fa tutto per pacchetti. <\/p>\n<p><\/p>\n<p>Quando deve leggere un certo intervallo di dati, legge un po' di pi\u00f9, perch\u00e9 l'indice in ClickHouse \u00e8 sparso. Questo indice non consente di trovare una singola riga nella tabella, solo un intervallo. E i dati vengono compressi in blocchi. Per leggere una riga, devi prendere un intero blocco e decomprimerlo. E se esegui molte richieste, ci saranno molte sovrapposizioni e una gran quantit\u00e0 di lavoro verr\u00e0 svolta ripetutamente.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey 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, possiamo notare che in ClickHouse non bisogna temere di passare anche megabyte e anche centinaia di megabyte nella sezione IN. Ricordo dalla nostra esperienza che se in MySQL passiamo un sacco di valori nella sezione IN, ad esempio, 100 megabyte di numeri, MySQL consuma 10 gigabyte di memoria e poi non succede pi\u00f9 nulla, tutto funziona male. <\/p>\n<p><\/p>\n<p>Il secondo punto \u00e8 che in ClickHouse, se le vostre query usano un indice, non \u00e8 mai pi\u00f9 lento di una scansione completa, cio\u00e8 se \u00e8 necessario leggere quasi tutta la tabella, proceder\u00e0 in modo sequenziale e legger\u00e0 l'intera tabella. Insomma, si gestir\u00e0 da solo.<\/p>\n<p><\/p>\n<p>Tuttavia, ci sono alcune difficolt\u00e0. Ad esempio, la sezione IN con una subquery non utilizza l'indice. Ma questo \u00e8 un nostro problema e dobbiamo risolverlo. Non c'\u00e8 nulla di fondamentale qui. Ci metteremo a ripararlo. <\/p>\n<p><\/p>\n<p>E un'altra cosa interessante \u00e8 che se avete una query molto lunga e si sta effettuando un'elaborazione distribuita delle query, questa query molto lunga verr\u00e0 inviata a ciascun server senza compressione. Ad esempio, 100 megabyte e 500 server. E, di conseguenza, verranno trasferiti 50 gigabyte attraverso la rete. Sar\u00e0 trasmesso e poi tutto verr\u00e0 eseguito con successo.<\/p>\n<p><\/p>\n<p>* gi\u00e0 in uso; tutto sistemato come promesso.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/5fcde9bf04fff0645be2530daa12743f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00c8 un caso piuttosto comune quando le richieste provengono da un'API. Ad esempio, avete creato un vostro servizio. E se il vostro servizio \u00e8 richiesto, avete aperto un'API e gi\u00e0 dopo due giorni vedete che sta succedendo qualcosa di strano. Tutto \u00e8 sovraccarico e pervengono richieste anomale che non avrebbero mai dovuto esserci. <\/p>\n<p><\/p>\n<p>E la soluzione \u00e8 una sola. Se hai aperto un'API, sar\u00e0 necessario limitarla. Ad esempio, puoi introdurre delle quote. Non ci sono altre opzioni ragionevoli. Altrimenti, verr\u00e0 subito scritto uno script e avrai problemi. <\/p>\n<p><\/p>\n<p>In ClickHouse c'\u00e8 una funzionalit\u00e0 speciale: il conteggio delle quote. \u00c8 possibile anche passare la tua chiave di quota. Questo \u00e8, ad esempio, un identificatore interno dell'utente. E le quote verranno calcolate in modo indipendente per ciascuno di essi. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/532438d0f116919e62f04e32ebbd3c45.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ora c'\u00e8 un'altra cosa interessante. Questa \u00e8 la replicazione a comando manuale. <\/p>\n<p><\/p>\n<p>Conosco molti casi in cui, nonostante ClickHouse abbia un supporto incorporato per la replicazione, le persone replicano ClickHouse manualmente.<\/p>\n<p><\/p>\n<p>Qual \u00e8 il principio? Avete una pipeline di elaborazione dei dati. E funziona in modo indipendente, ad esempio, in diversi data center. Registrate gli stessi dati nello stesso modo in ClickHouse, in un certo senso. Tuttavia, la pratica mostra che i dati finiranno comunque per divergere a causa di alcune peculiarit\u00e0 nel vostro codice. Spero che non sia il vostro caso. <\/p>\n<p><\/p>\n<p>E periodicamente voi 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 in ClickHouse. Ma ci possono essere alcune controindicazioni, perch\u00e9 per questo \u00e8 necessario utilizzare ZooKeeper. Non dir\u00f2 nulla di negativo su ZooKeeper, in linea di principio, il sistema funziona, ma a volte le persone non lo usano a causa della java-fobia, perch\u00e9 ClickHouse \u00e8 un ottimo sistema, scritto in C++, che pu\u00f2 essere utilizzato e funzioner\u00e0 alla grande. E ZooKeeper \u00e8 in java. E in qualche modo non si ha voglia di guardarci, ma a quel punto potete usare la replicazione manuale. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey 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 a comando manuale, potete creare una tabella Distributed che monitori le vostre repliche manuali e gestisca automaticamente il failover. Esiste persino un'opzione speciale che consente di evitare i problemi, anche se le vostre repliche si discostano sistematicamente.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/70f6630f8b14756163923a7db8dd7391.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Possono sorgere problemi se utilizzate motori di tabella primitivi. ClickHouse \u00e8 un costruttore dotato di una variet\u00e0 di motori di tabella. In tutti i casi seri, come indicato nella documentazione, utilizzate le tabelle della famiglia MergeTree. Tutti gli altri sono per casi speciali o per test.<\/p>\n<p><\/p>\n<p>Nella tabella MergeTree non \u00e8 necessario avere una data e un orario. Potete comunque utilizzarla. Se non avete data e ora, specificate che il default \u00e8 il 2000. Questo funzioner\u00e0 senza richiedere risorse. <\/p>\n<p><\/p>\n<p>Nella nuova versione del server, \u00e8 anche possibile specificare un partizionamento personalizzato senza una chiave di partizione. Sar\u00e0 la stessa cosa. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey 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 semplici motori di tabelle. Ad esempio, caricare i dati una volta e vedere, ruotare e rimuovere. Puoi utilizzare Log.<\/p>\n<p><\/p>\n<p>Oppure memorizzare piccole quantit\u00e0 per l'elaborazione intermedia \u2013 questo \u00e8 StripeLog o TinyLog.<\/p>\n<p><\/p>\n<p>Memory pu\u00f2 essere utilizzato se si tratta di una piccola quantit\u00e0 di dati e vuoi semplicemente ruotare qualcosa in RAM. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey 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 eccessivamente normalizzati. <\/p>\n<p><\/p>\n<p>Ecco un esempio tipico. Ci sono un'enorme quantit\u00e0 di URL. Li hai messi in una tabella separata. Poi hai deciso di fare un JOIN con loro, ma questo non funzioner\u00e0, di norma, perch\u00e9 ClickHouse supporta solo Hash JOIN. Se la memoria non \u00e8 sufficiente per un gran numero di dati con cui fare un join, il JOIN non potr\u00e0 essere eseguito*. <\/p>\n<p><\/p>\n<p>Se i dati hanno una grande cardinalit\u00e0, non preoccuparti, conservali in forma denormalizzata, gli URL direttamente inplace nella tabella principale. <\/p>\n<p><\/p>\n<p>* ora in ClickHouse ci sono anche merge join e funzionano in condizioni in cui i dati intermedi non possono essere contenuti in memoria. Ma questo non \u00e8 efficiente e la raccomandazione rimane valida.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/e8160a8db17c18d48f810092c55b094c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Un altro paio di esempi, ma ho gi\u00e0 dei dubbi se siano anti-modelli o meno. <\/p>\n<p><\/p>\n<p>In ClickHouse c'\u00e8 un noto svantaggio. Non supporta gli aggiornamenti*. In un certo senso, questo \u00e8 anche un bene. Se hai dei dati importanti, come la contabilit\u00e0, nessuno potr\u00e0 modificarli, perch\u00e9 non ci sono aggiornamenti.<\/p>\n<p><\/p>\n<p>* da tempo \u00e8 stata aggiunta la supporto per update e delete in modalit\u00e0 batch.<\/p>\n<p><\/p>\n<p>Tuttavia, ci sono alcuni metodi speciali che consentono di effettuare aggiornamenti in background. Ad esempio, le tabelle di tipo ReplaceMergeTree. Esse eseguono aggiornamenti durante le fusioni in background. Puoi forzarlo usando il comando optimize table. Ma non farlo troppo spesso, perch\u00e9 questo comporterebbe una riscrittura completa della partizione. <\/p>\n<p><\/p>\n<p>I JOIN distribuiti in ClickHouse sono anche gestiti male dal pianificatore di query. <\/p>\n<p><\/p>\n<p>\u00c8 problematico, ma a volte va bene.<\/p>\n<p><\/p>\n<p>Usare ClickHouse solo per leggere dati tramite select*.<\/p>\n<p><\/p>\n<p>Non consiglierei di utilizzare ClickHouse per operazioni di calcolo impegnative. Ma non \u00e8 proprio cos\u00ec, perch\u00e9 stiamo gi\u00e0 deviando da questa raccomandazione. Recentemente abbiamo aggiunto la possibilit\u00e0 di applicare modelli di machine learning in ClickHouse \u2013 Catboost. E questo mi preoccupa, perch\u00e9 penso: \u201cChe orrore. Quanti cicli per byte ci sono?!\u201d. Mi dispiace molto sprecare cicli per byte. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Uso efficace di ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/f686d5d352ccb444cd06e2ae68897137.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ma non preoccupatevi, installate ClickHouse, andr\u00e0 tutto bene. Se avete bisogno, abbiamo una comunit\u00e0. A proposito, la comunit\u00e0 siete voi. E se avete qualche problema, potete almeno entrare nella nostra chat e, spero, riceverete aiuto. <\/p>\n<p><\/p>\n<p>Domande<\/p>\n<p><\/p>\n<p><em>Grazie per la presentazione! Dove posso segnalare un malfunzionamento di ClickHouse?<\/em><\/p>\n<p><\/p>\n<p>Potete segnalarmelo direttamente adesso. <\/p>\n<p><\/p>\n<p><em>Ho appena iniziato a usare ClickHouse. Ho subito fatto cadere l'interfaccia cli.<\/em><\/p>\n<p><\/p>\n<p>Vi \u00e8 andata bene. <\/p>\n<p><\/p>\n<p><em>Poco dopo ho fatto cadere il server con una piccola select.<\/em><\/p>\n<p><\/p>\n<p>Siete davvero dotati. <\/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>Aleksey mi ha attirato nella presentazione con la promessa di spiegarmi come compressate i dati.<\/em><\/p>\n<p><\/p>\n<p>\u00c8 molto semplice. <\/p>\n<p><\/p>\n<p><em>L'ho capito solo ieri. Serve pi\u00f9 specificit\u00e0.<\/em> <\/p>\n<p><\/p>\n<p>Non ci sono trucchi terribili. Si tratta semplicemente di compressione a blocchi. Per impostazione predefinita, si usa LZ4, ma si pu\u00f2 attivare ZSTD*. I blocchi variano da 64 kilobyte a 1 megabyte.<\/p>\n<p><\/p>\n<p>* ci sono anche codec di compressione specializzati supportati che possono essere usati in combinazione con altri algoritmi.<\/p>\n<p><\/p>\n<p><em>I dati nei blocchi sono semplicemente grezzi?<\/em><\/p>\n<p><\/p>\n<p>Non proprio grezzi. Ci sono array. Se hai una colonna numerica, i numeri sono riposti consecutivamente in un array. <\/p>\n<p><\/p>\n<p><em>Capito.<\/em> <\/p>\n<p><\/p>\n<p><em>Alexey, un esempio simile a uniqExact con gli indirizzi IP, cio\u00e8, che uniqExact viene calcolato pi\u00f9 lentamente per le stringhe rispetto ai numeri, e cos\u00ec via. E se applicassimo un trucco e facessimo il casting al momento della lettura? Cio\u00e8, avete detto che su disco non ci sono grandi differenze. Se leggiamo le stringhe da disco, facciamo il casting, allora i nostri aggregati saranno pi\u00f9 veloci o no? O comunque ne guadagneremo solo in modo trascurabile? Mi sembra che l'abbiate testato, ma per qualche motivo non lo avete indicato nel benchmark.<\/em> <\/p>\n<p><\/p>\n<p>Penso che sar\u00e0 pi\u00f9 lento rispetto a senza casting. In questo caso, l'indirizzo IP deve essere analizzato dalla stringa. Certo, in ClickHouse l'analisi degli indirizzi IP \u00e8 anche ottimizzata. Abbiamo fatto del nostro meglio, ma l\u00ec avete i numeri scritti in forma decimale. \u00c8 molto scomodo. D'altra parte, la funzione uniqExact funzioner\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 prendiamo un tipo di dato pi\u00f9 primitivo? Ad esempio, abbiamo registrato un user id, che abbiamo in, l'abbiamo scritto come stringa e poi effettuato il casting, sar\u00e0 pi\u00f9 divertente o no?<\/em><\/p>\n<p><\/p>\n<p>Ho dei dubbi. Penso che sia ancora pi\u00f9 triste, perch\u00e9 analizzare numeri \u00e8 una questione seria. Mi sembra che quel collega avesse persino fatto una presentazione su quanto sia difficile analizzare i numeri in forma di diecimila, o forse no. <\/p>\n<p><\/p>\n<p><em>Alexey, grazie mille per la presentazione! E grazie ancora per ClickHouse! Ho una domanda riguardo ai piani. C'\u00e8 in programma una funzionalit\u00e0 per aggiornare i dizionari in modo parziale?<\/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 impostare un campo MySQL, cio\u00e8 aggiornare dopo, per caricare solo quei dati, se il dizionario \u00e8 molto grande.<\/em><\/p>\n<p><\/p>\n<p>Una funzionalit\u00e0 molto interessante. E mi sembra che qualcuno l'avesse proposta nella nostra chat. Potresti essere stato tu. <\/p>\n<p><\/p>\n<p><em>Non credo di essere stato io.<\/em><\/p>\n<p><\/p>\n<p>Ottimo, adesso sembra che ci siano due richieste. E si pu\u00f2 iniziare a lavorarci con calma. Ma voglio avvertirti che questa funzionalit\u00e0 \u00e8 piuttosto semplice da implementare. Cio\u00e8, in teoria, dovresti solo scrivere il numero di versione nella tabella e poi scrivere: versione inferiore a tale. E questo significa che probabilmente suggeriremo di farlo agli appassionati. Sei un appassionato? <\/p>\n<p><\/p>\n<p><em>S\u00ec, ma purtroppo 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 possibilit\u00e0 \u00e8 stata aggiunta due mesi dopo la presentazione \u2013 \u00e8 stata sviluppata dall\u2019autore della domanda e inviata <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>Buongiorno! Grazie per la presentazione! Hai menzionato che ClickHouse utilizza molto bene tutte le risorse disponibili. E il relatore accanto a Luxoft parlava della sua soluzione per Posta Russia. Ha detto che a loro \u00e8 piaciuto molto ClickHouse, ma non lo hanno utilizzato 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. C'\u00e8 un modo per limitare ClickHouse in modo che non consumi tutto ci\u00f2 che gli diventa disponibile?<\/em><\/p>\n<p><\/p>\n<p>S\u00ec, \u00e8 possibile e molto facile. Se vuoi che consumi meno core, basta scrivere <code>set max_threads = 1<\/code>. E tutto, eseguir\u00e0 la query su un solo core. Inoltre, puoi specificare impostazioni diverse per diversi utenti. Quindi nessun problema. E fai sapere ai colleghi di Luxoft che non \u00e8 corretto che non abbiano trovato questa impostazione nella documentazione. <\/p>\n<p><\/p>\n<p><em>Ciao Alexey! Vorrei chiederti qualcosa. Ho sentito pi\u00f9 volte che molti iniziano a usare ClickHouse come archivio per i log. Durante la presentazione hai detto di non farlo, ossia che non \u00e8 necessario memorizzare stringhe lunghe. Qual \u00e8 la tua opinione al riguardo?<\/em><\/p>\n<p><\/p>\n<p>Innanzitutto, i log di solito non sono stringhe lunghe. Ci sono, ovviamente, delle eccezioni. Ad esempio, un servizio scritto in Java pu\u00f2 generare un'eccezione che viene registrata. E questo pu\u00f2 avvenire in un ciclo infinito, riempiendo lo spazio su disco rigido. 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 pi\u00f9 recenti di ClickHouse, \u00e8 stata inclusa \"la granularit\u00e0 adattiva dell'indice\", che risolve in gran parte il problema dello storage di stringhe lunghe.<\/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 questo in chat, ma non ricordo se ho ricevuto risposta. \u00c8 previsto un ampliamento della sezione WITH nel modo del CTE?<\/em><\/p>\n<p><\/p>\n<p>Per il momento no. La sezione WITH \u00e8 piuttosto insignificante. \u00c8 una funzionalit\u00e0 secondaria.<\/p>\n<p><\/p>\n<p><em>Ho capito. Grazie!<\/em><\/p>\n<p><\/p>\n<p><em>Grazie per la relazione! \u00c8 molto interessante! Domanda globale. \u00c8 in programma di implementare, forse in forma di placeholder, una modifica per l'eliminazione dei dati?<\/em><\/p>\n<p><\/p>\n<p>Assolutamente. Questo \u00e8 il nostro primo compito nella nostra lista. Stiamo attualmente pianificando come fare tutto correttamente. E bisogna iniziare a premere sulla tastiera*.<\/p>\n<p><\/p>\n<p>* abbiamo premuto i tasti della tastiera e abbiamo fatto tutto.<\/p>\n<p><\/p>\n<p><em>Questo influenzer\u00e0 in qualche modo le prestazioni del sistema? L'inserimento sar\u00e0 veloce come adesso?<\/em><\/p>\n<p><\/p>\n<p>\u00c8 possibile che le operazioni di delete e update siano molto pesanti, ma questo non influenzer\u00e0 le prestazioni delle operazioni di select e insert.<\/p>\n<p><\/p>\n<p><em>E un'altra piccola domanda. Nella presentazione hai parlato della chiave primaria. Di conseguenza, abbiamo una partizione che per impostazione predefinita \u00e8 mensile, giusto? E quando impostiamo un intervallo di date che rientra in un mese, leggiamo solo quella partizione, corretto?<\/em><\/p>\n<p><\/p>\n<p>S\u00ec.<\/p>\n<p><\/p>\n<p><em>Ho una domanda. Se non possiamo identificare una chiave primaria, \u00e8 corretto utilizzare il campo \"Data\" per ridurre al minimo la ristrutturazione dei dati in background, in modo che siano organizzati in modo pi\u00f9 ordinato? Se non avete richieste in intervallo e non potete scegliere 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 utilizzare nella chiave primaria un campo per il quale i dati si comprimerebbero meglio se sono ordinati secondo quel campo. Ad esempio, l'ID utente. Un utente visita lo stesso sito. In questo caso, inserite l'ID utente e l'orario. Cos\u00ec facendo, i dati si comprimeranno meglio. Per quanto riguarda la data, se non avete e non avete mai richieste in intervallo per date, allora non \u00e8 necessario includere la data nella chiave primaria. <\/p>\n<p><\/p>\n<p><em>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.0.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.0.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. Alexey 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}]}}