{"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\/fr\/blog\/administrirovanie\/effektivnoe-ispolzovanie-clickhouse-aleksej-milovidov-yandeks","title":{"rendered":"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/8e42c1fffffcc964eacef240ea90bbc5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Comme ClickHouse est un syst\u00e8me sp\u00e9cialis\u00e9, il est important de prendre en compte les particularit\u00e9s de son architecture lors de son utilisation. Dans cette pr\u00e9sentation, Alexey \u00e9voquera des exemples d'erreurs typiques li\u00e9es \u00e0 l'utilisation de ClickHouse, qui peuvent entra\u00eener une performance inefficace. Des exemples pratiques montreront comment le choix d'un sch\u00e9ma de traitement des donn\u00e9es peut changer la performance de mani\u00e8re significative.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Bonjour \u00e0 tous ! Je m'appelle Alexey, je travaille avec ClickHouse.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/7f5fc01663be58d3d25e518a4169b8cf.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Tout d'abord, je suis heureux de vous annoncer que je ne vais pas vous expliquer aujourd'hui ce qu'est ClickHouse. Honn\u00eatement, j'en ai assez de le faire. Je le pr\u00e9sente \u00e0 chaque fois. Et, probablement, tout le monde est d\u00e9j\u00e0 au courant. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/fae6bd07d098200643d591b8e5bf51e8.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00c0 la place, je vais aborder les pi\u00e8ges possibles, c'est-\u00e0-dire comment ClickHouse peut \u00eatre mal utilis\u00e9. En r\u00e9alit\u00e9, il n'y a pas de quoi s'inqui\u00e9ter, car nous d\u00e9veloppons ClickHouse comme un syst\u00e8me simple, pratique, qui fonctionne d\u00e8s l'installation. Il suffit de l'installer, et tout est pr\u00eat, sans aucun probl\u00e8me. <\/p>\n<p><\/p>\n<p>Cependant, il faut garder \u00e0 l'esprit que ce syst\u00e8me est sp\u00e9cialis\u00e9, et il est facile de tomber sur un sc\u00e9nario d'utilisation inhabituel qui sortira le syst\u00e8me de sa zone de confort.<\/p>\n<p><\/p>\n<p>Alors, quels sont ces pi\u00e8ges ? Je vais principalement aborder les points \u00e9vidents. Tout le monde comprend tout, et peut se r\u00e9jouir d'\u00eatre intelligent, et ceux qui ne comprennent pas apprendront quelque chose de nouveau. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/bffacf353ff31b361460178e911f0e16.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Le premier exemple tr\u00e8s simple, qui, malheureusement, se rencontre souvent, c'est un grand nombre d'inserts avec de petits lots, c'est-\u00e0-dire une multitude de petits inserts.<\/p>\n<p><\/p>\n<p>Si l'on consid\u00e8re comment ClickHouse effectue un insert, vous pouvez envoyer un flux de donn\u00e9es d'un t\u00e9raoctet en une seule requ\u00eate. Ce n'est pas un probl\u00e8me. <\/p>\n<p><\/p>\n<p>Jetons un \u0153il \u00e0 la performance typique. Par exemple, nous avons une table avec des donn\u00e9es de Yandex.Metrica. Des hits. 105 colonnes diverses. 700 octets en brut. Et nous allons ins\u00e9rer correctement des lots d'un million de lignes. <\/p>\n<p><\/p>\n<p>Nous ins\u00e9rons dans une table MergeTree, ce qui donne un demi-million de lignes par seconde. Excellent. Dans une table r\u00e9pliqu\u00e9e, ce sera un peu moins, environ 400 000 lignes par seconde. <\/p>\n<p><\/p>\n<p>Et si nous activons l'insertion par quorum, nous obtenons un peu moins, mais tout de m\u00eame une performance respectable, 250 000 lignes par seconde. L'insertion par quorum est une fonctionnalit\u00e9 non document\u00e9e dans ClickHouse*.<\/p>\n<p><\/p>\n<p>* au 2020 <noindex><a rel=\"nofollow\" href=\"https:\/\/clickhouse.tech\/docs\/en\/operations\/settings\/settings\/#settings-insert_quorum\">elle est d\u00e9j\u00e0 document\u00e9e<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/668498fc82a0f6e851d05e6e1ea67033.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Que se passe-t-il si cela se fait mal ? Nous ins\u00e9rons une ligne \u00e0 la fois dans la table MergeTree et cela donne 59 lignes par seconde. C'est 10 000 fois plus lent. Avec ReplicatedMergeTree, c'est 6 lignes par seconde. Et si en plus le quorum est activ\u00e9, cela tombe \u00e0 2 lignes par seconde. \u00c0 mon avis, c'est un v\u00e9ritable d\u00e9sastre. Comment peut-on avoir un tel ralentissement ? M\u00eame sur mon T-shirt, il est \u00e9crit que ClickHouse ne doit pas ramer. Pourtant, cela arrive parfois. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/4c771eddc4e8453f60ef91123ae5d109.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>En r\u00e9alit\u00e9, c'est notre d\u00e9faut. Nous aurions pu faire en sorte que tout fonctionne correctement, mais nous ne l'avons pas fait. Et nous ne l'avons pas fait parce que pour notre sc\u00e9nario, ce n'\u00e9tait pas n\u00e9cessaire. Nous avions d\u00e9j\u00e0 des lots. Les donn\u00e9es arrivaient sous forme de lots, sans aucun probl\u00e8me. Nous ins\u00e9rons et tout fonctionne bien. Mais bien s\u00fbr, divers sc\u00e9narios sont possibles. Par exemple, lorsque vous avez plusieurs serveurs sur lesquels les donn\u00e9es sont g\u00e9n\u00e9r\u00e9es. Et ils ins\u00e8rent des donn\u00e9es pas si souvent, mais les insertions restent fr\u00e9quentes. Il faut donc \u00e9viter cela d'une mani\u00e8re ou d'une autre. <\/p>\n<p><\/p>\n<p>D'un point de vue technique, l'essentiel est qu'au moment o\u00f9 vous effectuez un insert dans ClickHouse, les donn\u00e9es n'atterrissent dans aucune memtable. Nous n'avons m\u00eame pas de MergeTree \u00e0 structure de journal v\u00e9ritable, mais simplement un MergeTree, car il n'y a ni journal ni memTable. Nous \u00e9crivons directement les donn\u00e9es dans le syst\u00e8me de fichiers, d\u00e9j\u00e0 dispos\u00e9es par colonnes. Et si vous avez 100 colonnes, il faudra \u00e9crire plus de 200 fichiers dans un r\u00e9pertoire distinct. Tout cela est assez lourd. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/24688fe3d39d81b92f12ac1b8b21425b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Et la question se pose : \u00ab Comment faire correctement ? \u00bb, si nous devons quand m\u00eame enregistrer des donn\u00e9es dans ClickHouse.<\/p>\n<p><\/p>\n<p>M\u00e9thode 1. C'est la m\u00e9thode la plus simple. Utiliser une sorte de file d'attente distribu\u00e9e. Par exemple, Kafka. Vous extrayez simplement les donn\u00e9es de Kafka, vous les regroupez toutes les secondes. Et tout ira bien, vous ins\u00e9rez, tout fonctionne correctement. <\/p>\n<p><\/p>\n<p>Les inconv\u00e9nients sont que Kafka est encore un syst\u00e8me distribu\u00e9 encombrant. Je peux comprendre si votre entreprise dispose d\u00e9j\u00e0 de Kafka. C'est bien, c'est pratique. Mais s'il n'est pas l\u00e0, il vaut mieux r\u00e9fl\u00e9chir \u00e0 deux fois avant d'introduire un autre syst\u00e8me distribu\u00e9 dans votre projet. C'est pourquoi il vaut la peine d'envisager des alternatives. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/4f687221e8c7443abf02fb002c4eba5b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>M\u00e9thode 2. Voici une alternative old-school qui est tr\u00e8s simple. Vous avez un serveur qui g\u00e9n\u00e8re vos journaux. Il enregistre simplement vos journaux dans un fichier. Vous renommez ce fichier une fois par seconde, par exemple, et ouvrez un nouveau. Un script distinct, soit via cron, soit un daemon, prend le fichier le plus ancien et l'enregistre dans ClickHouse. Si vous enregistrez les journaux une fois par seconde, tout ira bien. <\/p>\n<p><\/p>\n<p>Mais l'inconv\u00e9nient de cette m\u00e9thode est que si le serveur qui g\u00e9n\u00e8re les journaux dispara\u00eet, les donn\u00e9es dispara\u00eetront aussi.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/b4c28b6df87386c42b6908bdfccb6b90.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>M\u00e9thode 3. Il existe une autre m\u00e9thode int\u00e9ressante qui ne n\u00e9cessite pas de fichiers temporaires. Par exemple, vous avez une sorte de service publicitaire ou un autre daemon int\u00e9ressant qui g\u00e9n\u00e8re des donn\u00e9es. Vous pouvez accumuler un ensemble de donn\u00e9es directement en m\u00e9moire, dans un tampon. Lorsque suffisamment de temps s'est \u00e9coul\u00e9, vous mettez ce tampon de c\u00f4t\u00e9, cr\u00e9ez un nouveau, et dans un fil distinct, vous ins\u00e9rez ce qui a d\u00e9j\u00e0 \u00e9t\u00e9 accumul\u00e9 dans ClickHouse.<\/p>\n<p><\/p>\n<p>D'un autre c\u00f4t\u00e9, les donn\u00e9es disparaissent \u00e9galement avec un kill -9. Si votre serveur s'effondre, ces donn\u00e9es seront perdues. Et un autre probl\u00e8me est que si vous ne parvenez pas \u00e0 les enregistrer dans la base, vous accumulerez des donn\u00e9es en m\u00e9moire. Cela peut soit \u00e9puiser votre m\u00e9moire vive, soit simplement entra\u00eener une perte de donn\u00e9es. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/dc375b22fcb26cfa111d0bdb4563aa88.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>M\u00e9thode 4. Voici une autre m\u00e9thode int\u00e9ressante. Vous avez un processus serveur. Il peut envoyer des donn\u00e9es directement \u00e0 ClickHouse, mais le faire dans une seule connexion. Par exemple, envoyer une requ\u00eate http avec transfer-encoding: chunked avec un insert. Et il g\u00e9n\u00e8re des chunks pas trop rarement, vous pouvez envoyer chaque ligne, bien qu'il y ait un overhead li\u00e9 \u00e0 l'encodage de ces donn\u00e9es. <\/p>\n<p><\/p>\n<p>Cependant, dans ce cas, les donn\u00e9es seront imm\u00e9diatement envoy\u00e9es \u00e0 ClickHouse. Et ClickHouse les mettra lui-m\u00eame en m\u00e9moire tampon. <\/p>\n<p><\/p>\n<p>Mais il y a \u00e9galement des probl\u00e8mes. Vous perdrez des donn\u00e9es, notamment lorsque votre processus se termine et si le processus ClickHouse se termine, car cela sera un insert inachev\u00e9. Les inserts dans ClickHouse sont atomiques jusqu'\u00e0 un certain seuil sp\u00e9cifi\u00e9 en nombre de lignes. En principe, c'est une m\u00e9thode int\u00e9ressante. On peut \u00e9galement l'utiliser.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/6a18a974b9600ade377a870390e95d3d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>M\u00e9thode 5. Voici une autre m\u00e9thode int\u00e9ressante. Il s'agit d'un serveur con\u00e7u par la communaut\u00e9 pour le traitement par lots de donn\u00e9es. Je ne l'ai pas examin\u00e9 moi-m\u00eame, donc je ne peux rien garantir. Cela dit, aucune garantie n'est fournie pour ClickHouse non plus. C'est \u00e9galement open source, mais d'un autre c\u00f4t\u00e9, vous avez peut-\u00eatre pris l'habitude d'un certain standard de qualit\u00e9 que nous nous effor\u00e7ons de respecter. Quant \u00e0 cette fonctionnalit\u00e9 \u2013 je ne sais pas, allez sur GitHub, consultez le code. Peut-\u00eatre ont-ils \u00e9crit quelque chose de correct. <\/p>\n<p><\/p>\n<p>* \u00e0 partir de 2020, il convient \u00e9galement d'inclure \u00e0 l'examen <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=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/ae6a04af63ae4e7fa160c002fdb6d506.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>M\u00e9thode 6. Une autre m\u00e9thode consiste \u00e0 utiliser des tables Buffer. Les avantages de cette m\u00e9thode sont qu'il est tr\u00e8s facile de commencer \u00e0 l'utiliser. Vous cr\u00e9ez une table Buffer et vous y ins\u00e9rez vos donn\u00e9es. <\/p>\n<p><\/p>\n<p>L'inconv\u00e9nient est que le probl\u00e8me n'est pas compl\u00e8tement r\u00e9solu. Si, lors de l'insertion avec MergeTree, vous devez grouper les donn\u00e9es par un seul lot par seconde, lors de l'insertion dans une table Buffer, vous devez grouper au moins jusqu'\u00e0 quelques milliers par seconde. Si cela d\u00e9passe 10 000 par seconde, cela ne fonctionnera toujours pas correctement. En ins\u00e9rant par lots, vous pourriez constater que cela atteint des centaines de milliers de lignes par seconde. Et cela m\u00eame avec des donn\u00e9es relativement lourdes. <\/p>\n<p><\/p>\n<p>Et aussi, les tables Buffer n'ont pas de journal. Et si quelque chose ne va pas avec votre serveur, les donn\u00e9es seront perdues. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/9bb16bf5e8145cc8368b11e54c86c837.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Et en bonus, r\u00e9cemment, nous avons ajout\u00e9 la possibilit\u00e9 de r\u00e9cup\u00e9rer des donn\u00e9es de Kafka dans ClickHouse. Il existe un moteur de table \u2013 Kafka. Vous n'avez qu'\u00e0 le cr\u00e9er. Et vous pouvez y attacher des vues mat\u00e9rialis\u00e9es. Dans ce cas, il extraira automatiquement les donn\u00e9es de Kafka et les ins\u00e9rera dans les tables dont vous avez besoin. <\/p>\n<p><\/p>\n<p>Ce qui est particuli\u00e8rement r\u00e9jouissant dans cette fonctionnalit\u00e9, c'est qu'elle n'a pas \u00e9t\u00e9 d\u00e9velopp\u00e9e par nous. C'est une fonctionnalit\u00e9 de la communaut\u00e9. Et quand je dis \u00ab fonctionnalit\u00e9 de la communaut\u00e9 \u00bb, je le dis sans aucun m\u00e9pris. Nous avons consult\u00e9 le code, fait des revues, cela devrait fonctionner normalement. <\/p>\n<p><\/p>\n<p>* \u00e0 partir de 2020, un support similaire a \u00e9t\u00e9 ajout\u00e9 pour <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=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/15dc61dfd435f5f8640395b7de480fe2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Qu'est-ce qui peut encore \u00eatre inconfortable ou inattendu lors de l'insertion de donn\u00e9es ? Si vous effectuez une requ\u00eate insert values et que dans values vous \u00e9crivez des expressions calcul\u00e9es. Par exemple, now() \u2013 c'est aussi une expression calcul\u00e9e. Et dans ce cas, ClickHouse doit ex\u00e9cuter l'interpr\u00e9teur de ces expressions pour chaque ligne, ce qui va consid\u00e9rablement d\u00e9grader les performances. Il vaut mieux \u00e9viter cela.<\/p>\n<p><\/p>\n<p>* Le probl\u00e8me est maintenant enti\u00e8rement r\u00e9solu, il n'y a plus de r\u00e9gression de performance lors de l'utilisation d'expressions dans VALUES.<\/p>\n<p><\/p>\n<p>Un autre exemple o\u00f9 des probl\u00e8mes peuvent survenir est lorsque vous avez des donn\u00e9es d'un seul lot qui concernent de nombreuses partitions. Par d\u00e9faut, ClickHouse partitionne par mois. Et si vous ins\u00e9rez un lot d'un million de lignes contenant des donn\u00e9es sur plusieurs ann\u00e9es, vous aurez plusieurs dizaines de partitions. Cela \u00e9quivaut \u00e0 avoir des lots de tailles consid\u00e9rablement r\u00e9duites, car \u00e0 l'int\u00e9rieur, ils sont d'abord divis\u00e9s par partitions.<\/p>\n<p><\/p>\n<p>* R\u00e9cemment, ClickHouse a ajout\u00e9 en mode exp\u00e9rimental le support d'un format compact pour les morceaux et les morceaux en m\u00e9moire avec un journal de pr\u00e9-\u00e9criture, ce qui r\u00e9sout presque compl\u00e8tement le probl\u00e8me.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/b8c6cecdba53559dad31ed11713a980d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Passons maintenant au deuxi\u00e8me type de probl\u00e8me \u2013 le typage des donn\u00e9es. <\/p>\n<p><\/p>\n<p>Le typage des donn\u00e9es peut \u00eatre strict ou bas\u00e9 sur des cha\u00eenes. Le typage bas\u00e9 sur des cha\u00eenes signifie que vous avez simplement d\u00e9clar\u00e9 que tous vos champs sont de type string. C'est inacceptable. Il ne faut pas faire \u00e7a. <\/p>\n<p><\/p>\n<p>Voyons comment faire correctement dans les cas o\u00f9 vous souhaitez dire qu'un champ est une cha\u00eene, et laissez ClickHouse s'en occuper, sans vous inqui\u00e9ter. Mais il vaut quand m\u00eame la peine de faire un effort. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/a0fdcf6423933293318411242fe2ede7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Par exemple, nous avons une adresse IP. Dans un cas, nous l'avons enregistr\u00e9e en tant que cha\u00eene. Par exemple, 192.168.1.1. Dans un autre cas, cela sera un nombre de type UInt32*. 32 bits suffisent pour une adresse IPv4.<\/p>\n<p><\/p>\n<p>Tout d'abord, \u00e9trangement, les donn\u00e9es seront compress\u00e9es de mani\u00e8re \u00e0 peu pr\u00e8s identique. Il y aura des diff\u00e9rences, bien s\u00fbr, mais elles ne seront pas si importantes. Donc, il n'y a pas de probl\u00e8mes majeurs concernant l'entr\u00e9e\/sortie disque. <\/p>\n<p><\/p>\n<p>Cependant, il y a une diff\u00e9rence significative en termes de temps processeur et de temps d'ex\u00e9cution des requ\u00eates. <\/p>\n<p><\/p>\n<p>Calculons le nombre d'adresses IP uniques si elles sont stock\u00e9es sous forme de nombres. On obtient 137 millions de lignes par seconde. Si c'est la m\u00eame chose sous forme de cha\u00eenes, alors c'est 37 millions de lignes par seconde. Je ne sais pas pourquoi cette co\u00efncidence s'est produite. J'ai r\u00e9alis\u00e9 ces requ\u00eates moi-m\u00eame. Mais n\u00e9anmoins, c'est environ 4 fois plus lent. <\/p>\n<p><\/p>\n<p>Et si nous comparons la diff\u00e9rence en espace disque, il y a aussi une diff\u00e9rence. Et cette diff\u00e9rence est d'environ un quart, car il y a suffisamment d'adresses IP uniques. Et s'il y avait des lignes avec un faible nombre de valeurs diff\u00e9rentes, elles auraient facilement \u00e9t\u00e9 compress\u00e9es par dictionnaire en un volume \u00e0 peu pr\u00e8s identique. <\/p>\n<p><\/p>\n<p>Et il n'y a pas de diff\u00e9rence de temps sur la route, peu importe dans quelle mesure cela vous importe. Mais quand je vois une telle diff\u00e9rence, cela me rend triste.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/f74dbfdab5a9e26fa044a5870a8cc00d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Examinons diff\u00e9rents cas. <\/p>\n<p><\/p>\n<p>1. Un cas o\u00f9 vous avez peu de valeurs uniques. Dans ce cas, nous utilisons une pratique simple que vous connaissez s\u00fbrement et que vous pouvez appliquer \u00e0 n'importe quel SGBD. Cela a du sens non seulement pour ClickHouse. Vous enregistrez simplement des identifiants num\u00e9riques dans la base. La conversion en cha\u00eenes et vice versa peut \u00eatre effectu\u00e9e d\u00e9j\u00e0 du c\u00f4t\u00e9 de votre application. <\/p>\n<p><\/p>\n<p>Par exemple, vous avez une r\u00e9gion. Et vous essayez de la sauvegarder sous forme de cha\u00eene. Cela va s'\u00e9crire : Moscou et MO. Et quand je vois qu'il est \u00e9crit \u00ab Moscou \u00bb, c'est encore rien, mais quand c'est aussi MO, cela devient un peu triste. Combien de bytes cela repr\u00e9sente. <\/p>\n<p><\/p>\n<p>Au lieu de cela, nous enregistrons simplement le nombre Ulnt32 et 250. Nous avons 250 dans Yandex, et chez vous, cela peut \u00eatre diff\u00e9rent. Au cas o\u00f9 je pr\u00e9ciserais que ClickHouse dispose d'une fonctionnalit\u00e9 int\u00e9gr\u00e9e pour travailler avec une base g\u00e9ographique. Vous enregistrez simplement un r\u00e9pertoire des r\u00e9gions, y compris hi\u00e9rarchique, c'est-\u00e0-dire qu'il y aura Moscou, MO et tout ce dont vous avez besoin. Et vous pouvez convertir au niveau de la requ\u00eate. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/cc6e871136dab8f8a35246a5af512cda.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>La deuxi\u00e8me option est \u00e0 peu pr\u00e8s la m\u00eame, mais avec le soutien interne de ClickHouse. C'est le type de donn\u00e9es Enum. Vous d\u00e9finissez simplement toutes les valeurs dont vous avez besoin \u00e0 l'int\u00e9rieur de l'Enum. Par exemple, le type d'appareil et l\u00e0, vous \u00e9crivez : ordinateur de bureau, mobile, tablette, t\u00e9l\u00e9vision. Au total, 4 variantes. <\/p>\n<p><\/p>\n<p>L'inconv\u00e9nient est qu'il faut parfois faire un alter. Vous avez ajout\u00e9 seulement une variante. Nous effectuons un alter table. En r\u00e9alit\u00e9, l'alter table dans ClickHouse est gratuit. Surtout pour Enum, car les donn\u00e9es sur disque ne changent pas. N\u00e9anmoins, l'alter bloque la table et doit attendre que toutes les s\u00e9lections soient ex\u00e9cut\u00e9es. Ce n'est qu'apr\u00e8s que l'alter sera ex\u00e9cut\u00e9, c'est-\u00e0-dire qu'il y a tout de m\u00eame certains inconv\u00e9nients.<\/p>\n<p><\/p>\n<p>* Dans les versions r\u00e9centes de ClickHouse, l'ALTER est compl\u00e8tement non-bloquant.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/d7284fa5be583ab063bb6de0b60f54d4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Une autre option assez unique pour ClickHouse est la connexion de dictionnaires externes. Vous pouvez \u00e9crire des nombres dans ClickHouse, tandis que vos dictionnaires peuvent \u00eatre maintenus dans n'importe quel syst\u00e8me qui vous convient. Par exemple, vous pouvez utiliser : MySQL, Mongo, Postgres. Vous pouvez m\u00eame cr\u00e9er votre propre microservice qui fournira ces donn\u00e9es via http. Et au niveau de ClickHouse, vous \u00e9crivez une fonction qui convertira ces donn\u00e9es des nombres en cha\u00eenes. <\/p>\n<p><\/p>\n<p>C'est une m\u00e9thode sp\u00e9cialis\u00e9e mais tr\u00e8s efficace pour effectuer un join avec une table externe. Il y a deux options. Dans une option, ces donn\u00e9es seront compl\u00e8tement mises en cache, totalement pr\u00e9sentes en m\u00e9moire et mises \u00e0 jour \u00e0 certaines intervalles. Dans l'autre option, si ces donn\u00e9es ne tiennent pas en m\u00e9moire, il est possible de les mettre en cache partiellement. <\/p>\n<p><\/p>\n<p>Voici un exemple. Il y a Yandex.Direct. Et l\u00e0, il y a des campagnes publicitaires et des banni\u00e8res. Il y a probablement environ dix millions de campagnes publicitaires. Et elles peuvent tenir en m\u00e9moire. Mais il y a des milliards de banni\u00e8res, elles ne peuvent pas tenir. Nous utilisons donc un dictionnaire cachable de MySQL.<\/p>\n<p><\/p>\n<p>Le seul probl\u00e8me est que le dictionnaire cachable fonctionnera correctement si le taux de r\u00e9ussite est proche de 100 %. S'il est plus faible, lors du traitement des requ\u00eates pour chaque lot de donn\u00e9es, il faudra r\u00e9ellement r\u00e9cup\u00e9rer les cl\u00e9s manquantes et aller r\u00e9cup\u00e9rer les donn\u00e9es dans MySQL. En ce qui concerne ClickHouse, je peux garantir qu'il ne ralentit pas, mais pour d'autres syst\u00e8mes, je ne me prononcerai pas.<\/p>\n<p><\/p>\n<p>Et en bonus, les dictionnaires sont un moyen tr\u00e8s simple de mettre \u00e0 jour les donn\u00e9es dans ClickHouse r\u00e9troactivement. C'est-\u00e0-dire que si vous aviez un rapport sur des campagnes publicitaires, et que l'utilisateur change simplement de campagne publicitaire, alors toutes ces anciennes donn\u00e9es, dans tous les rapports, seront \u00e9galement modifi\u00e9es. Si vous \u00e9crivez directement dans la table, il sera impossible de les mettre \u00e0 jour. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/a5a2919d6be7d00c0ad5875b9a8f0f31.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Une autre m\u00e9thode, lorsque vous ne savez pas d'o\u00f9 obtenir les identifiants pour vos lignes, est de simplement les hacher. Et la m\u00e9thode la plus simple consiste \u00e0 utiliser un hachage 64 bits. <\/p>\n<p><\/p>\n<p>Le seul probl\u00e8me est que si le hachage est de 64 bits, alors les collisions seront presque in\u00e9vitables. Parce que si vous avez un milliard de lignes, la probabilit\u00e9 devient significative. <\/p>\n<p><\/p>\n<p>Il ne serait pas tr\u00e8s sage de hacher ainsi les noms des campagnes publicitaires. Si les campagnes publicitaires de diff\u00e9rentes entreprises se m\u00e9langent, cela deviendra incompr\u00e9hensible. <\/p>\n<p><\/p>\n<p>Il existe un truc simple. Bien s\u00fbr, ce n\u2019est pas tr\u00e8s adapt\u00e9 pour des donn\u00e9es critiques, mais si ce n'est pas tr\u00e8s s\u00e9rieux, il suffit d'ajouter l'identifiant du client \u00e0 la cl\u00e9 du dictionnaire. Ainsi, vous aurez des collisions, mais uniquement dans le cadre d'un seul client. Cette m\u00e9thode est utilis\u00e9e pour la carte des liens dans Yandex.Metrica. Nous avons des URLs, nous stockons des hachages. Nous savons qu'il y a, bien s\u00fbr, des collisions. Mais quand la page est affich\u00e9e, la probabilit\u00e9 qu'un utilisateur ait des URLs qui se chevauchent sur une m\u00eame page et que cela soit remarqu\u00e9 peut \u00eatre n\u00e9glig\u00e9e. <\/p>\n<p><\/p>\n<p>En bonus, pour de nombreuses op\u00e9rations, des hachages suffisent et il n'est pas n\u00e9cessaire de stocker les cha\u00eenes elles-m\u00eames. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/abbb73aaba29d10e3b7e7650bf68e6a6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Un autre exemple, si les cha\u00eenes sont courtes, par exemple, les domaines de sites. Elles peuvent \u00eatre stock\u00e9es telles quelles. Ou, par exemple, la langue du navigateur ru \u2013 2 octets. Bien s\u00fbr, je suis un peu d\u00e9sol\u00e9 pour les octets, mais ne vous inqui\u00e9tez pas, 2 octets ne sont pas un probl\u00e8me. S'il vous pla\u00eet, stockez-les telles quelles, ne vous cassez pas la t\u00eate. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/901eaed0029da6ea59630b57ccf80c25.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Un autre cas, c'est quand il y a beaucoup de cha\u00eenes et qu'elles contiennent beaucoup d'\u00e9l\u00e9ments uniques, avec un nombre potentiellement illimit\u00e9. Un exemple typique \u2013 les phrases de recherche ou les URLs. Les phrases de recherche, notamment \u00e0 cause des fautes de frappe. Voyons combien de phrases de recherche uniques il y a par jour. Cela repr\u00e9sente presque la moiti\u00e9 de tous les \u00e9v\u00e9nements. Dans ce cas, vous pourriez penser qu'il faut normaliser les donn\u00e9es, calculer des identifiants et les stocker dans une table s\u00e9par\u00e9e. Mais ce n'est pas n\u00e9cessaire. Il suffit de conserver ces cha\u00eenes telles quelles. <\/p>\n<p><\/p>\n<p>Mieux vaut ne rien inventer, car si vous stockez s\u00e9par\u00e9ment, vous devrez faire un join. Et ce join \u2013 dans le meilleur des cas \u2013 n\u00e9cessitera un acc\u00e8s al\u00e9atoire \u00e0 la m\u00e9moire, si cela y tient encore. Si cela ne tient pas, cela posera effectivement des probl\u00e8mes. <\/p>\n<p><\/p>\n<p>Et si les donn\u00e9es sont stock\u00e9es in place, elles seront simplement lues dans le bon ordre depuis le syst\u00e8me de fichiers et tout ira bien.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/15f1d632083def16ccbc939579c1cf6b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Si vous avez des URLs ou une autre cha\u00eene complexe et longue, il peut \u00eatre utile de penser \u00e0 calculer une sorte de r\u00e9sum\u00e9 \u00e0 l'avance et \u00e0 le stocker dans une colonne s\u00e9par\u00e9e. <\/p>\n<p><\/p>\n<p>Pour les URLs, par exemple, il est possible de stocker le domaine s\u00e9par\u00e9ment. Et si vous avez vraiment besoin du domaine, utilisez simplement cette colonne, tandis que les URLs resteront alors o\u00f9 elles sont, et vous n'aurez m\u00eame pas \u00e0 y toucher. <\/p>\n<p><\/p>\n<p>Comparons la diff\u00e9rence. ClickHouse dispose d'une fonction sp\u00e9cialis\u00e9e qui calcule le domaine. Elle est tr\u00e8s rapide, nous l'avons optimis\u00e9e. Et, pour \u00eatre honn\u00eate, elle ne respecte m\u00eame pas la RFC, mais elle calcule n\u00e9anmoins tout ce dont nous avons besoin. <\/p>\n<p><\/p>\n<p>Dans un cas, nous allons simplement extraire les URL et calculer le domaine. Cela prend 166 millisecondes. Si nous prenons un domaine d\u00e9j\u00e0 pr\u00eat, cela ne prend que 67 millisecondes, soit presque trois fois plus vite. Et ce n'est pas parce que nous avons besoin de faire des calculs, mais parce que nous lisons moins de donn\u00e9es. <\/p>\n<p><\/p>\n<p>\u00c9tonnamment, pour une requ\u00eate plus lente, nous obtenons un plus grand d\u00e9bit en gigaoctets par seconde. Parce qu'elle lit plus de gigaoctets. Ce sont des donn\u00e9es totalement inutiles. La requ\u00eate fonctionne plus rapidement, mais prend plus de temps \u00e0 s'ex\u00e9cuter.<\/p>\n<p><\/p>\n<p>Si nous regardons la taille des donn\u00e9es sur le disque, l'URL fait 126 m\u00e9gaoctets, tandis que le domaine ne fait que 5 m\u00e9gaoctets. Cela repr\u00e9sente 25 fois moins. Pourtant, la requ\u00eate s'ex\u00e9cute seulement 4 fois plus vite. Mais c'est parce que les donn\u00e9es sont chaudes. Si elles \u00e9taient froides, cela aurait probablement \u00e9t\u00e9 25 fois plus rapide en raison des entr\u00e9es-sorties disque. <\/p>\n<p><\/p>\n<p>D'ailleurs, si nous \u00e9valuons \u00e0 quel point le domaine est plus petit que l'URL, nous nous retrouvons avec environ 4 fois moins. Pourtant, sur le disque, les donn\u00e9es occupent 25 fois moins. Pourquoi ? \u00c0 cause de la compression. Tant l'URL que le domaine sont compress\u00e9s. Mais souvent, l'URL contient beaucoup de d\u00e9chets. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/c93d2128a41561ed7abb25d77414bc2d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Bien s\u00fbr, il est essentiel d'utiliser les bons types de donn\u00e9es, sp\u00e9cifiquement con\u00e7us pour les valeurs n\u00e9cessaires ou les types appropri\u00e9s. Si vous utilisez IPv4, stockez en UInt32*. Si c'est IPv6, utilisez FixedString(16), car une adresse IPv6 fait 128 bits, donc stockez directement au format binaire. <\/p>\n<p><\/p>\n<p>Que faire si vous avez parfois des adresses IPv4 et parfois des IPv6 ? Oui, vous pouvez stocker les deux. Une colonne pour IPv4, une autre pour IPv6. Il existe \u00e9galement une option pour afficher IPv4 sous IPv6. Cela fonctionnera aussi, mais si vous avez souvent besoin d'une adresse IPv4 sp\u00e9cifique dans vos requ\u00eates, il serait pr\u00e9f\u00e9rable de la mettre dans une colonne s\u00e9par\u00e9e. <\/p>\n<p><\/p>\n<p>* Maintenant, ClickHouse dispose de types de donn\u00e9es distincts pour IPv4 et IPv6, qui stockent les donn\u00e9es aussi efficacement que les nombres, tout en les pr\u00e9sentant de mani\u00e8re aussi pratique que des cha\u00eenes.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/d7d6342ebd6b8b4f3526b3cd8a06cf26.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Il est \u00e9galement important de noter qu'il vaut mieux pr\u00e9traiter les donn\u00e9es \u00e0 l'avance. Par exemple, vous recevez des journaux bruts. Peut-\u00eatre qu'il n'est pas sage de les envoyer directement dans ClickHouse, m\u00eame s'il est tr\u00e8s tentant de ne rien faire et de laisser tout fonctionner. Mais il vaut mieux effectuer les calculs possibles.<\/p>\n<p><\/p>\n<p>Par exemple, la version du navigateur. Dans un d\u00e9partement voisin, que je pr\u00e9f\u00e8re ne pas pointer du doigt, la version du navigateur est conserv\u00e9e de cette mani\u00e8re, c'est-\u00e0-dire comme une cha\u00eene : 12.3. Ensuite, pour faire un rapport, ils prennent cette cha\u00eene, la divisent en tableau, puis prennent le premier \u00e9l\u00e9ment du tableau. \u00c9videmment, tout ralentit. J'ai demand\u00e9 pourquoi ils faisaient cela. Ils m'ont r\u00e9pondu qu'ils n'aimaient pas l'optimisation pr\u00e9matur\u00e9e. Personnellement, je n'aime pas la pessimisation pr\u00e9matur\u00e9e.<\/p>\n<p><\/p>\n<p>Dans ce cas, il serait donc plus judicieux de diviser en 4 colonnes. N'ayez pas peur, car c'est ClickHouse. ClickHouse est une base de donn\u00e9es orient\u00e9e colonne. Plus vous avez de petites colonnes soign\u00e9es, mieux c'est. Si vous avez 5 BrowserVersion, faites 5 colonnes. C'est normal. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/f9a67221bf8508933d7bd336b16f9e04.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Voyons maintenant que faire si vous avez beaucoup de cha\u00eenes tr\u00e8s longues, des tableaux tr\u00e8s longs. Ils n'ont pas besoin d'\u00eatre stock\u00e9s dans ClickHouse du tout. \u00c0 la place, vous pouvez enregistrer uniquement un identifiant dans ClickHouse. Et stockez ces longues cha\u00eenes dans un autre syst\u00e8me. <\/p>\n<p><\/p>\n<p>Par exemple, dans l'un de nos services d'analytique, nous avons certains param\u00e8tres d'\u00e9v\u00e9nements. Et si de nombreux param\u00e8tres arrivent pour les \u00e9v\u00e9nements, nous nous contentons de sauvegarder les premiers 512. Parce que 512, \u00e7a ne fait pas de mal. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/755271e8788ba4bd638f493bf320c820.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Et si vous ne savez pas quel type de donn\u00e9es utiliser, vous pouvez \u00e9galement enregistrer les donn\u00e9es dans ClickHouse, mais dans une table temporaire de type Log, sp\u00e9cialement con\u00e7ue pour les donn\u00e9es temporaires. Ensuite, vous pouvez analyser la distribution des valeurs que vous avez l\u00e0, et identifier les types appropri\u00e9s.<\/p>\n<p><\/p>\n<p>* Actuellement, ClickHouse a un type de donn\u00e9es <noindex><a rel=\"nofollow\" href=\"https:\/\/clickhouse.tech\/docs\/en\/sql-reference\/data-types\/lowcardinality\/\">LowCardinality<\/a><\/noindex> qui permet de stocker efficacement les cha\u00eenes avec moins de co\u00fbts en ressources.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/7e9e53d86a4189783c28ce56a669198c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Examinons maintenant un autre cas int\u00e9ressant. Parfois, les choses semblent fonctionner de mani\u00e8re \u00e9trange pour certaines personnes. Je me connecte et je vois cela. Et je suppose imm\u00e9diatement que cela a \u00e9t\u00e9 fait par un administrateur tr\u00e8s exp\u00e9riment\u00e9, intelligent, ayant une grande exp\u00e9rience dans la configuration de MySQL version 3.23. <\/p>\n<p><\/p>\n<p>Ici, nous voyons mille tables, chacune contenant un reste de la division de quelque chose d'incompr\u00e9hensible par mille. <\/p>\n<p><\/p>\n<p>En principe, je respecte l'exp\u00e9rience des autres et je comprends \u00e9galement quelles souffrances cette exp\u00e9rience peut engendrer. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/3a5e21ef2076966fcc627670485c5b3a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Les raisons sont plus ou moins claires. Ce sont de vieux st\u00e9r\u00e9otypes qui ont pu se former lors de l'utilisation d'autres syst\u00e8mes. Par exemple, dans les tables MyISAM, il n'y a pas de cl\u00e9 primaire clusteris\u00e9e. Et cette fa\u00e7on de diviser les donn\u00e9es peut \u00eatre une tentative d\u00e9sesp\u00e9r\u00e9e d'obtenir la m\u00eame fonctionnalit\u00e9. <\/p>\n<p><\/p>\n<p>Une autre raison est que toutes les op\u00e9rations de type alter sur de grandes tables sont difficiles \u00e0 r\u00e9aliser. Tout sera bloqu\u00e9. Bien que dans les versions modernes de MySQL, ce probl\u00e8me ne soit plus si s\u00e9rieux. <\/p>\n<p><\/p>\n<p>Ou, par exemple, le micro-sharding, mais j'en parlerai un peu plus tard.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/321b1d9caa8db7aca5b96e08c61d05b5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Dans ClickHouse, cela n'est pas n\u00e9cessaire, car premi\u00e8rement, la cl\u00e9 primaire est clusteris\u00e9e et les donn\u00e9es sont ordonn\u00e9es selon cette cl\u00e9 primaire. <\/p>\n<p><\/p>\n<p>Et parfois, on me demande : \u00ab Comment la performance des requ\u00eates par plage dans ClickHouse varie-t-elle selon la taille de la table ? \u00bb. Je r\u00e9ponds qu'elle ne varie pas. Par exemple, si vous avez une table d'un milliard de lignes et que vous lisez une plage d'un million de lignes, tout fonctionne bien. Si la table contient un trillion de lignes et que vous lisez un million de lignes, ce sera presque la m\u00eame chose. <\/p>\n<p><\/p>\n<p>Deuxi\u00e8mement, il n'est pas n\u00e9cessaire d'avoir des trucs comme des partitions manuelles. Si vous allez voir ce qu'il y a sur le syst\u00e8me de fichiers, vous verrez que la table est un \u00e9l\u00e9ment assez s\u00e9rieux. Et il y a quelque chose comme des partitions \u00e0 l'int\u00e9rieur. C'est-\u00e0-dire que ClickHouse fait tout pour vous et vous n'avez pas \u00e0 souffrir.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/652f3742ad3a44f172d0d7302abd09f6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>La commande alter dans ClickHouse est gratuite si vous effectuez un alter add\/drop column. <\/p>\n<p><\/p>\n<p>Et il n'est pas judicieux de cr\u00e9er de petites tables, car si votre table contient 10 lignes ou 10 000 lignes, cela n'a absolument aucun int\u00e9r\u00eat. ClickHouse est un syst\u00e8me qui optimise le throughput, pas la latence, donc traiter 10 lignes n'a pas de sens. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/144144b4740e9c5daec80c8dadc445f9.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Il est pr\u00e9f\u00e9rable d'utiliser une grande table. \u00c9liminez les vieux st\u00e9r\u00e9otypes, tout ira bien. <\/p>\n<p><\/p>\n<p>En bonus, notre derni\u00e8re version a introduit la possibilit\u00e9 de cr\u00e9er une cl\u00e9 de partitionnement arbitr\u00e9e pour effectuer diverses op\u00e9rations de maintenance sur des partitions sp\u00e9cifiques. <\/p>\n<p><\/p>\n<p>Par exemple, vous avez besoin de beaucoup de petites tables, par exemple lorsque vous devez traiter certaines donn\u00e9es interm\u00e9diaires, vous recevez des chunks et devez effectuer des transformations sur celles-ci avant de les enregistrer dans la table finale. Pour ce cas, il existe un moteur de table remarquable \u2013 StripeLog. C'est un peu comme TinyLog, mais en mieux. <\/p>\n<p><\/p>\n<p>* ClickHouse dispose \u00e9galement maintenant de <noindex><a rel=\"nofollow\" href=\"https:\/\/clickhouse.tech\/docs\/en\/sql-reference\/table-functions\/input\/\">la fonction de table input<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/d62f0b3d29876c29c6c0ba236b200186.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Un autre anti-pattern est le micro-sharding. Par exemple, vous devez shard les donn\u00e9es et vous avez 5 serveurs, mais demain il y en aura 6. Et vous r\u00e9fl\u00e9chissez \u00e0 la mani\u00e8re de r\u00e9\u00e9quilibrer ces donn\u00e9es. Au lieu de cela, vous divisez non pas en 5 shards, mais en 1 000 shards. Ensuite, vous assignez chacun de ces micro-shards \u00e0 un serveur distinct. Ainsi, vous pouvez vous retrouver avec par exemple 200 ClickHouse sur un seul serveur. Des instances s\u00e9par\u00e9es sur des ports distincts ou des bases de donn\u00e9es distinctes. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/3e550ef7e338b84e4394eb9fa4538769.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Mais dans ClickHouse, c'est pas tr\u00e8s bien. Parce qu'une seule instance de ClickHouse essaie d'utiliser toutes les ressources disponibles du serveur pour traiter une seule requ\u00eate. C'est-\u00e0-dire que si vous avez un serveur avec par exemple 56 c\u0153urs de processeur. Vous effectuez une requ\u00eate qui dure une seconde, et elle utilisera 56 c\u0153urs. Si vous avez plac\u00e9 200 ClickHouse sur un serveur, cela signifie qu'il y aura 10 000 threads qui d\u00e9marre. En gros, tout ira tr\u00e8s mal.<\/p>\n<p><\/p>\n<p>Une autre raison est que la r\u00e9partition du travail entre ces instances sera in\u00e9gale. Certaines termineront plus t\u00f4t, d'autres plus tard. Si tout cela se d\u00e9roulait dans une seule instance, ClickHouse saurait lui-m\u00eame r\u00e9partir correctement les donn\u00e9es entre les threads. <\/p>\n<p><\/p>\n<p>Et une autre raison est que vous aurez une interaction interprocessus via TCP. Les donn\u00e9es devront \u00eatre s\u00e9rialis\u00e9es, d\u00e9s\u00e9rialis\u00e9es et cela implique un nombre \u00e9norme de micro-shards. Ce sera tout simplement inefficace.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/18cacc17d22ae1cb2977c6be74769896.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Un autre anti-pattern, bien qu'il soit difficile de le qualifier d\u2019anti-pattern. C'est une grande quantit\u00e9 de pr\u00e9-agr\u00e9gation.<\/p>\n<p><\/p>\n<p>En g\u00e9n\u00e9ral, la pr\u00e9-agr\u00e9gation, c'est bien. Vous aviez un milliard de lignes, vous l'avez agr\u00e9g\u00e9 et cela a donn\u00e9 1 000 lignes, ce qui fait que la requ\u00eate s'ex\u00e9cute instantan\u00e9ment. Tout est merveilleux. C'est possible. Et pour cela, ClickHouse dispose m\u00eame d'un type de table sp\u00e9cial, AggregatingMergeTree, qui effectue une agr\u00e9gation incr\u00e9mentale lors de l'insertion des donn\u00e9es. <\/p>\n<p><\/p>\n<p>Mais il arrive que vous pensiez que nous allons agr\u00e9ger les donn\u00e9es de cette mani\u00e8re et encore de cette mani\u00e8re. Et dans un d\u00e9partement voisin, sans vouloir dire lequel, ils utilisent des tables SummingMergeTree pour faire des sommes par cl\u00e9 primaire, et comme cl\u00e9 primaire, ils utilisent une vingtaine de colonnes. J'ai chang\u00e9 par pr\u00e9caution les noms de certaines colonnes pour des raisons de confidentialit\u00e9, mais c'est \u00e0 peu pr\u00e8s \u00e7a.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/54e3a02ab4bbce7c63ded595780ae1f6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Et cela pose certains probl\u00e8mes. Tout d'abord, le volume de donn\u00e9es ne diminue pas beaucoup. Par exemple, il est r\u00e9duit par trois. Trois fois \u2014 ce serait un bon rapport pour permettre des possibilit\u00e9s d'analyse illimit\u00e9es qui \u00e9mergent si vos donn\u00e9es ne sont pas agr\u00e9g\u00e9es. Si les donn\u00e9es sont agr\u00e9g\u00e9es, vous recevez au lieu de l'analyse, une simple statistique mis\u00e9rable. <\/p>\n<p><\/p>\n<p>Et ce qui est particuli\u00e8rement aga\u00e7ant ? C'est que ces personnes du d\u00e9partement voisin viennent parfois et demandent d'ajouter encore une colonne \u00e0 la cl\u00e9 primaire. C'est-\u00e0-dire que nous avions agr\u00e9gu\u00e9 les donn\u00e9es de cette mani\u00e8re, et maintenant nous en voulons un peu plus. Mais dans ClickHouse, il n'y a pas de commande pour modifier la cl\u00e9 primaire. Donc, il faut \u00e9crire des scripts en C++. Et je n'aime pas les scripts, m\u00eame s'ils sont en C++.<\/p>\n<p><\/p>\n<p>Et si l'on regarde \u00e0 quoi ClickHouse a \u00e9t\u00e9 con\u00e7u, les donn\u00e9es non agr\u00e9g\u00e9es sont exactement le sc\u00e9nario pour lequel il a \u00e9t\u00e9 cr\u00e9\u00e9. Si vous utilisez ClickHouse pour des donn\u00e9es non agr\u00e9g\u00e9es, vous faites tout correctement. Si vous agglom\u00e9rez, c'est parfois pardonnable. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/09fafd4c8a3ea8c22e586cb7a5cf6564.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Un autre cas int\u00e9ressant concerne les requ\u00eates en boucle infinie. Il m'arrive parfois de me connecter \u00e0 un serveur de production et de v\u00e9rifier la liste des processus. Et \u00e0 chaque fois, je d\u00e9couvre que quelque chose d'horrible se produit. <\/p>\n<p><\/p>\n<p>Par exemple, cela. Ici, il est \u00e9vident que tout aurait pu \u00eatre ex\u00e9cut\u00e9 dans une seule requ\u00eate. Il suffit d'\u00e9crire l\u00e0-dedans url in et la liste.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/ae03b659f178962f50e0640614517296.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Pourquoi avoir beaucoup de telles requ\u00eates en boucle infinie est-il mauvais ? Si l'index n'est pas utilis\u00e9, vous aurez de nombreux passages sur les m\u00eames donn\u00e9es. Mais si l'index est utilis\u00e9, par exemple, vous avez une cl\u00e9 primaire sur ru et vous \u00e9crivez url = quelque chose. Et vous pensez qu'il sera lu pr\u00e9cis\u00e9ment un url de la table, cela ira. Mais en r\u00e9alit\u00e9, non. Parce que ClickHouse fait tout par lots. <\/p>\n<p><\/p>\n<p>Lorsqu'il doit lire une certaine plage de donn\u00e9es, il en lit un peu plus, car l'index dans ClickHouse est sparse. Cet index ne permet pas de trouver une seule ligne individuelle dans la table, seulement une certaine plage. De plus, les donn\u00e9es sont compress\u00e9es par blocs. Pour lire une ligne, il faut prendre un bloc entier et le d\u00e9compresser. Et si vous ex\u00e9cutez beaucoup de requ\u00eates, il y aura de nombreux chevauchements et une grande quantit\u00e9 de travail sera effectu\u00e9e encore et encore.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/95eef43c5b869f8b145c61ce3c616cfd.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Et en bonus, on peut noter qu'il n'est pas n\u00e9cessaire d'avoir peur de transmettre m\u00eame des m\u00e9gaoctets, voire des centaines de m\u00e9gaoctets dans la section IN dans ClickHouse. Je me souviens de notre exp\u00e9rience, que si dans MySQL on transmet une multitude de valeurs dans la section IN, par exemple, si l'on y met 100 m\u00e9gaoctets de chiffres, MySQL consume 10 gigaoctets de m\u00e9moire et ensuite rien ne se passe, tout fonctionne mal. <\/p>\n<p><\/p>\n<p>Et la deuxi\u00e8me chose est que dans ClickHouse, si vos requ\u00eates utilisent un index, cela n'est jamais plus lent qu'un scan complet, c'est-\u00e0-dire que si presque toute la table doit \u00eatre lue, il va le faire de mani\u00e8re s\u00e9quentielle et lire toute la table. En g\u00e9n\u00e9ral, il comprend tout lui-m\u00eame.<\/p>\n<p><\/p>\n<p>Cependant, il y a certaines difficult\u00e9s. Par exemple, le fait que IN avec une sous-requ\u00eate n'utilise pas l'index. Mais c'est notre probl\u00e8me et nous devons le corriger. Il n'y a rien de fondamental ici. Nous allons le r\u00e9parer. <\/p>\n<p><\/p>\n<p>Et une autre chose int\u00e9ressante est que si vous avez une tr\u00e8s longue requ\u00eate et que le traitement des requ\u00eates est distribu\u00e9, alors cette tr\u00e8s longue requ\u00eate sera envoy\u00e9e \u00e0 chaque serveur sans compression. Par exemple, 100 m\u00e9gaoctets et 500 serveurs. Et, par cons\u00e9quent, vous aurez 50 gigaoctets transmis sur le r\u00e9seau. Ils seront transmis et ensuite tout s'ex\u00e9cutera avec succ\u00e8s.<\/p>\n<p><\/p>\n<p>* utilise d\u00e9j\u00e0 ; tout est r\u00e9par\u00e9, comme promis.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/5fcde9bf04fff0645be2530daa12743f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Et c'est assez fr\u00e9quent que les requ\u00eates viennent de l'API. Par exemple, vous avez cr\u00e9\u00e9 votre propre service. Et si votre service est n\u00e9cessaire \u00e0 quelqu'un, vous avez ouvert une API et litt\u00e9ralement deux jours plus tard, vous voyez que quelque chose d'incompr\u00e9hensible se produit. Tout est surcharg\u00e9 et des requ\u00eates horribles arrivent, qui n'auraient jamais d\u00fb exister. <\/p>\n<p><\/p>\n<p>Et la solution ici est simple. Si vous avez ouvert l'API, vous devrez la limiter. Par exemple, introduire des quotas. Il n'y a pas d'autres options normales. Sinon, quelqu'un \u00e9crira imm\u00e9diatement un script et il y aura des probl\u00e8mes. <\/p>\n<p><\/p>\n<p>ClickHouse dispose d'une fonctionnalit\u00e9 sp\u00e9ciale : le comptage des quotas. Vous pouvez \u00e9galement transmettre votre cl\u00e9 de quota, par exemple, un identifiant interne d'utilisateur. Les quotas seront compt\u00e9s ind\u00e9pendamment pour chacun d'eux. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/532438d0f116919e62f04e32ebbd3c45.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Maintenant, une autre chose int\u00e9ressante. C'est la r\u00e9plication manuelle. <\/p>\n<p><\/p>\n<p>Je connais de nombreux cas o\u00f9, m\u00eame si ClickHouse prend en charge la r\u00e9plication int\u00e9gr\u00e9e, les gens r\u00e9pliquent ClickHouse manuellement.<\/p>\n<p><\/p>\n<p>Quel est le principe ? Vous avez un pipeline de traitement des donn\u00e9es qui fonctionne ind\u00e9pendamment, par exemple, dans diff\u00e9rents centres de donn\u00e9es. Vous enregistrez les m\u00eames donn\u00e9es de la m\u00eame mani\u00e8re dans ClickHouse. Cependant, en pratique, il s'av\u00e8re que les donn\u00e9es vont quand m\u00eame diverger en raison de certaines particularit\u00e9s de votre code. J'esp\u00e8re que cela ne sera pas le cas dans le v\u00f4tre. <\/p>\n<p><\/p>\n<p>Et p\u00e9riodiquement, vous devrez quand m\u00eame synchroniser manuellement. Par exemple, une fois par mois, les administrateurs effectuent un rsync.<\/p>\n<p><\/p>\n<p>En r\u00e9alit\u00e9, il est beaucoup plus simple d'utiliser la r\u00e9plication int\u00e9gr\u00e9e \u00e0 ClickHouse. Mais cela peut avoir certaines contre-indications, car cela n\u00e9cessite d'utiliser ZooKeeper. Je ne dirai rien de mal sur ZooKeeper, en principe, c'est un syst\u00e8me fonctionnel, mais il arrive que les gens ne l'utilisent pas en raison d'une phobie de Java, car ClickHouse est un bon syst\u00e8me \u00e9crit en C++, qui fonctionne tr\u00e8s bien. Et ZooKeeper est en Java. Il est donc parfois difficile de regarder cela, mais dans ce cas, vous pouvez utiliser la r\u00e9plication manuelle. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/3b5b68996daef6b8920f067b189f25e0.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>ClickHouse est un syst\u00e8me pragmatique. Il prend en compte vos besoins. Si vous avez une r\u00e9plication manuelle, vous pouvez cr\u00e9er une table Distributed qui regarde vos r\u00e9pliques manuelles et effectue elle-m\u00eame un failover entre elles. Il existe m\u00eame une option sp\u00e9ciale qui permet d'\u00e9viter les flaps, m\u00eame si vos r\u00e9pliques divergent syst\u00e9matiquement.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/70f6630f8b14756163923a7db8dd7391.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Par la suite, des probl\u00e8mes peuvent survenir si vous utilisez des moteurs de table primitifs. ClickHouse est un constructeur qui dispose d'une multitude de diff\u00e9rents moteurs de table. Pour tous les cas s\u00e9rieux, comme indiqu\u00e9 dans la documentation, utilisez des tables de la famille MergeTree. Les autres options sont juste pour des cas sp\u00e9cifiques ou pour des tests.<\/p>\n<p><\/p>\n<p>Dans une table MergeTree, il n'est pas n\u00e9cessaire d'avoir une date et une heure. Vous pouvez utiliser cette option. Si vous n'avez pas de date et d'heure, indiquez que la valeur par d\u00e9faut est l'ann\u00e9e 2000. Cela fonctionnera et ne n\u00e9cessitera pas beaucoup de ressources. <\/p>\n<p><\/p>\n<p>Dans la nouvelle version du serveur, vous pouvez m\u00eame sp\u00e9cifier que vous souhaitez un partitionnement personnalis\u00e9 sans cl\u00e9 de partition. Ce sera la m\u00eame chose. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/6d4046d11afdd1e5962d49a1612b666a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>D'un autre c\u00f4t\u00e9, vous pouvez utiliser des moteurs de table primitifs. Par exemple, chargez les donn\u00e9es une fois et regardez, manipulez et supprimez. Vous pouvez utiliser Log.<\/p>\n<p><\/p>\n<p>Ou stocker de petits volumes pour un traitement interm\u00e9diaire \u2013 c'est StripeLog ou TinyLog.<\/p>\n<p><\/p>\n<p>Memory peut \u00eatre utilis\u00e9 si le volume de donn\u00e9es est petit et que vous devez simplement manipuler quelque chose en m\u00e9moire. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/8a3d4e0e3a8c26dd3a2b2f64123e2bf9.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>ClickHouse n'aime pas vraiment les donn\u00e9es sur-normalis\u00e9es. <\/p>\n<p><\/p>\n<p>Voici un exemple typique. Il s'agit d'un \u00e9norme nombre d'URLs. Vous les avez mises dans une table adjacente. Ensuite, vous avez d\u00e9cid\u00e9 de faire un JOIN avec elles, mais cela ne fonctionnera g\u00e9n\u00e9ralement pas, car ClickHouse ne prend en charge que les Hash JOIN. Si vous manquez de m\u00e9moire pour un grand volume de donn\u00e9es \u00e0 relier, le JOIN ne pourra pas \u00eatre effectu\u00e9*. <\/p>\n<p><\/p>\n<p>Si les donn\u00e9es ont une grande cardinalit\u00e9, ne vous inqui\u00e9tez pas, conservez-les sous une forme d\u00e9normalis\u00e9e, les URLs directement inplace dans la table principale. <\/p>\n<p><\/p>\n<p>* En fait, ClickHouse dispose maintenant \u00e9galement d'un merge join, et il fonctionne lorsque les donn\u00e9es interm\u00e9diaires ne tiennent pas en m\u00e9moire. Mais ce n'est pas efficace, et la recommandation reste valable.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/e8160a8db17c18d48f810092c55b094c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Encore quelques exemples, mais je commence \u00e0 douter s'ils sont antipattern ou non. <\/p>\n<p><\/p>\n<p>ClickHouse a un inconv\u00e9nient bien connu. Il ne prend pas en charge les mises \u00e0 jour*. D'une certaine mani\u00e8re, c'est m\u00eame une bonne chose. Si vous avez des donn\u00e9es importantes, par exemple la comptabilit\u00e9, personne ne pourra les modifier, car il n'y a pas de mises \u00e0 jour.<\/p>\n<p><\/p>\n<p>* Le support des mises \u00e0 jour et des suppressions en mode batch a \u00e9t\u00e9 ajout\u00e9 depuis longtemps.<\/p>\n<p><\/p>\n<p>Mais il existe quelques m\u00e9thodes sp\u00e9ciales qui permettent de faire des mises \u00e0 jour en quelque sorte en arri\u00e8re-plan. Par exemple, les tables de type ReplaceMergeTree. Elles effectuent des mises \u00e0 jour lors des fusions en arri\u00e8re-plan. Vous pouvez forcer cela en utilisant optimize table. Mais ne le faites pas trop souvent, car cela entra\u00eenera une r\u00e9\u00e9criture compl\u00e8te de la partition. <\/p>\n<p><\/p>\n<p>Les JOIN distribu\u00e9s dans ClickHouse sont \u00e9galement mal g\u00e9r\u00e9s par le planificateur de requ\u00eates. <\/p>\n<p><\/p>\n<p>C'est mauvais, mais parfois \u00e7a va.<\/p>\n<p><\/p>\n<p>Utiliser ClickHouse uniquement pour lire les donn\u00e9es avec un select*.<\/p>\n<p><\/p>\n<p>Je ne recommanderais pas d'utiliser ClickHouse pour des calculs intensifs. Cependant, cela ne refl\u00e8te pas tout \u00e0 fait la r\u00e9alit\u00e9, car nous nous \u00e9loignons d\u00e9j\u00e0 de cette recommandation. Nous avons r\u00e9cemment ajout\u00e9 la possibilit\u00e9 d'appliquer des mod\u00e8les d'apprentissage automatique dans ClickHouse \u2013 Catboost. Cela m'inqui\u00e8te, car je me dis : \u00ab Quel d\u00e9sastre. Combien de cycles par octet cela repr\u00e9sente-t-il ! \u00bb. Je d\u00e9teste voir des cycles utilis\u00e9s pour des octets. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Utilisation efficace de ClickHouse. Alexe\u00ef Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/f686d5d352ccb444cd06e2ae68897137.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Mais ne vous inqui\u00e9tez pas, installez ClickHouse, tout ira bien. En cas de probl\u00e8me, nous avons une communaut\u00e9. N'oubliez pas, cette communaut\u00e9, c'est vous. Et si vous rencontrez des difficult\u00e9s, vous pouvez au moins rejoindre notre chat, et j'esp\u00e8re que vous recevrez de l'aide. <\/p>\n<p><\/p>\n<p>Questions<\/p>\n<p><\/p>\n<p><em>Merci pour la pr\u00e9sentation ! O\u00f9 puis-je signaler une chute de ClickHouse ?<\/em><\/p>\n<p><\/p>\n<p>Vous pouvez me signaler personnellement d\u00e8s maintenant. <\/p>\n<p><\/p>\n<p><em>J'ai r\u00e9cemment commenc\u00e9 \u00e0 utiliser ClickHouse. J'ai imm\u00e9diatement plant\u00e9 l'interface CLI.<\/em><\/p>\n<p><\/p>\n<p>Vous avez de la chance. <\/p>\n<p><\/p>\n<p><em>Un peu plus tard, j'ai fait planter le serveur avec une simple requ\u00eate SELECT.<\/em><\/p>\n<p><\/p>\n<p>Vous avez un talent. <\/p>\n<p><\/p>\n<p><em>J'ai ouvert un bug sur GitHub, mais il a \u00e9t\u00e9 ignor\u00e9.<\/em> <\/p>\n<p><\/p>\n<p>Nous verrons. <\/p>\n<p><\/p>\n<p><em>Alexey m'a tromp\u00e9 pour me convaincre d'assister \u00e0 la pr\u00e9sentation en promettant de montrer comment vous compressez les donn\u00e9es.<\/em><\/p>\n<p><\/p>\n<p>C'est tr\u00e8s simple. <\/p>\n<p><\/p>\n<p><em>Je l'ai compris hier. Plus de pr\u00e9cision.<\/em> <\/p>\n<p><\/p>\n<p>Il n'y a pas de trucs horribles. C'est simplement une compression par blocs. Par d\u00e9faut, LZ4 est utilis\u00e9, ZSTD peut \u00eatre activ\u00e9. Les blocs vont de 64 Ko \u00e0 1 Mo.<\/p>\n<p><\/p>\n<p>* il existe \u00e9galement un soutien pour des codecs de compression sp\u00e9cialis\u00e9s qui peuvent \u00eatre utilis\u00e9s en cha\u00eene avec d'autres algorithmes.<\/p>\n<p><\/p>\n<p><em>Les blocs contiennent simplement des donn\u00e9es brutes ?<\/em><\/p>\n<p><\/p>\n<p>Pas tout \u00e0 fait brutes. Cela contient des tableaux. Si vous avez une colonne num\u00e9rique, les nombres seront organis\u00e9s dans un tableau. <\/p>\n<p><\/p>\n<p><em>Compris.<\/em> <\/p>\n<p><\/p>\n<p><em>Alexey, l'exemple avec uniqExact sur les adresses IP, c'est-\u00e0-dire le fait que uniqExact prend plus de temps \u00e0 calculer sur des cha\u00eenes que sur des nombres, etc. Et si nous utilisons un stratag\u00e8me et castons au moment de la lecture ? C'est-\u00e0-dire, vous avez dit que sur le disque, cela ne diff\u00e8re pas beaucoup. Si nous lisons des cha\u00eenes sur le disque et castons, alors nos agr\u00e9gats seront-ils plus rapides ou non ? Ou allons-nous tout de m\u00eame gagner ici de mani\u00e8re n\u00e9gligeable ? J'ai l'impression que vous avez test\u00e9 cela, mais vous ne l'avez pas mentionn\u00e9 dans le benchmark.<\/em> <\/p>\n<p><\/p>\n<p>Je pense que cela sera plus lent qu'en dehors du cast. Dans ce cas, l'adresse IP doit \u00eatre analys\u00e9e \u00e0 partir de la cha\u00eene. Bien s\u00fbr, dans ClickHouse, l'analyse des adresses IP est \u00e9galement optimis\u00e9e. Nous avons vraiment fait des efforts, mais vous avez des nombres \u00e9crits en forme de dizaines de milliers. C'est tr\u00e8s peu pratique. D'un autre c\u00f4t\u00e9, la fonction uniqExact va fonctionner plus lentement sur des cha\u00eenes, non seulement parce que ce sont des cha\u00eenes, mais aussi parce qu'une autre sp\u00e9cialisation de l'algorithme est choisie. Les cha\u00eenes sont simplement trait\u00e9es diff\u00e9remment.<\/p>\n<p><\/p>\n<p><em>Et si on prenait un type de donn\u00e9es plus primitif ? Par exemple, on a \u00e9crit l'user id, qui est dans notre cas, on l'a \u00e9crit sous forme de cha\u00eene, et puis on a fait un cast, ce sera plus amusant ou pas ?<\/em><\/p>\n<p><\/p>\n<p>J'en doute. Je pense que ce sera m\u00eame plus triste, car analyser des nombres est un v\u00e9ritable probl\u00e8me. Il me semble que l'un de mes coll\u00e8gues avait m\u00eame fait une pr\u00e9sentation sur la difficult\u00e9 d'analyser des nombres sous la forme de dizaines de milliers, ou peut-\u00eatre pas. <\/p>\n<p><\/p>\n<p><em>Alexey, merci beaucoup pour ta pr\u00e9sentation ! Et encore merci pour ClickHouse ! J'ai une question concernant les fonctionnalit\u00e9s. Y a-t-il des projets pour une mise \u00e0 jour partielle des dictionnaires ?<\/em><\/p>\n<p><\/p>\n<p>C'est-\u00e0-dire un rechargement partiel ?<\/p>\n<p><\/p>\n<p><em>Oui, oui. Une sorte de possibilit\u00e9 de d\u00e9finir un champ MySQL, c'est-\u00e0-dire de mettre \u00e0 jour apr\u00e8s, pour que seules ces donn\u00e9es soient charg\u00e9es, si le dictionnaire est tr\u00e8s volumineux.<\/em><\/p>\n<p><\/p>\n<p>C'est une fonction tr\u00e8s int\u00e9ressante. Et, il me semble qu'une personne l'a propos\u00e9e dans notre chat. C'\u00e9tait peut-\u00eatre m\u00eame vous. <\/p>\n<p><\/p>\n<p><em>Je ne pense pas.<\/em><\/p>\n<p><\/p>\n<p>Super, donc cela fait deux requ\u00eates. Et on peut commencer \u00e0 le faire tranquillement. Mais je veux vous pr\u00e9venir tout de suite que cette fonctionnalit\u00e9 est assez simple \u00e0 mettre en \u0153uvre. C'est-\u00e0-dire qu'en th\u00e9orie, il suffit d'\u00e9crire le num\u00e9ro de version dans la table et ensuite d'\u00e9crire : version inf\u00e9rieure \u00e0 telle version. Et cela signifie que, tr\u00e8s probablement, nous proposerons de le faire aux enthousiastes. \u00cates-vous un enthousiaste ? <\/p>\n<p><\/p>\n<p><em>Oui, mais, malheureusement, pas en C++.<\/em><\/p>\n<p><\/p>\n<p>Vos coll\u00e8gues savent-ils \u00e9crire en C++ ? <\/p>\n<p><\/p>\n<p><em>Je vais trouver quelqu'un.<\/em><\/p>\n<p><\/p>\n<p>Super*.<\/p>\n<p><\/p>\n<p>* la fonctionnalit\u00e9 a \u00e9t\u00e9 ajout\u00e9e deux mois apr\u00e8s la pr\u00e9sentation \u2013 elle a \u00e9t\u00e9 d\u00e9velopp\u00e9e par l'auteur de la question et a \u00e9t\u00e9 envoy\u00e9 <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/ClickHouse\/ClickHouse\/pull\/1771\">pull request<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p><em>Merci!<\/em><\/p>\n<p><\/p>\n<p><em>Bonjour ! Merci pour la pr\u00e9sentation ! Vous avez mentionn\u00e9 que ClickHouse consomme tr\u00e8s bien toutes les ressources qui lui sont disponibles. Et le pr\u00e9sentateur voisin de Luxoft a parl\u00e9 de sa solution pour la Poste de Russie. Il a dit qu'ils aimaient beaucoup ClickHouse, mais qu'ils ne l'avaient pas utilis\u00e9 \u00e0 la place de leur principal concurrent pr\u00e9cis\u00e9ment parce qu'il utilisait tout le processeur. Et ils n'ont pas pu l'int\u00e9grer dans leur architecture, dans leur ZooKeeper avec des Docker. Existe-t-il un moyen de limiter ClickHouse afin qu'il ne consomme pas tout ce qui lui est accessible ?<\/em><\/p>\n<p><\/p>\n<p>Oui, c'est possible et tr\u00e8s facile. Si vous souhaitez qu'il consomme moins de c\u0153urs, il suffit d'\u00e9crire <code>set max_threads = 1<\/code>. Et voil\u00e0, il ex\u00e9cutera la requ\u00eate sur un seul c\u0153ur. De plus, vous pouvez indiquer cette configuration diff\u00e9rente pour divers utilisateurs. Donc, aucun probl\u00e8me. Et dites \u00e0 vos coll\u00e8gues de Luxoft qu'il n'est pas bon qu'ils n'aient pas trouv\u00e9 cette option dans la documentation. <\/p>\n<p><\/p>\n<p><em>Alexei, bonjour ! J'aimerais poser une question. Je n'entends pas pour la premi\u00e8re fois que beaucoup commencent \u00e0 utiliser ClickHouse comme stockage pour les journaux. Lors de votre pr\u00e9sentation, vous avez dit de ne pas faire cela, c'est-\u00e0-dire qu'il ne faut pas stocker de longues cha\u00eenes. Que pensez-vous de cela ?<\/em><\/p>\n<p><\/p>\n<p>Tout d'abord, les journaux ne sont g\u00e9n\u00e9ralement pas de longues cha\u00eenes. Il y a bien s\u00fbr des exceptions. Par exemple, un service \u00e9crit en Java g\u00e9n\u00e8re une exception qui est enregistr\u00e9e. Et cela dans une boucle infinie, et l'espace sur le disque dur se termine. La solution est tr\u00e8s simple. Si les cha\u00eenes sont tr\u00e8s longues, coupez-les. Et que signifie longues ? Des dizaines de kilo-octets, c'est mauvais*.<\/p>\n<p><\/p>\n<p>* dans les derni\u00e8res versions de ClickHouse, l'\u00ab adaptabilit\u00e9 de la granularit\u00e9 de l'index \u00bb a \u00e9t\u00e9 int\u00e9gr\u00e9e, ce qui r\u00e9sout en grande partie le probl\u00e8me du stockage de longues cha\u00eenes.<\/p>\n<p><\/p>\n<p><em>Et un kilo-octet, c'est normal ?<\/em><\/p>\n<p><\/p>\n<p>C'est normal. <\/p>\n<p><\/p>\n<p><em>Bonjour ! Merci pour la pr\u00e9sentation ! J'ai d\u00e9j\u00e0 demand\u00e9 cela dans le chat, mais je ne me souviens pas si j'ai re\u00e7u une r\u00e9ponse. Pr\u00e9voyez-vous d'\u00e9largir la section WITH \u00e0 la mani\u00e8re des CTE ?<\/em><\/p>\n<p><\/p>\n<p>Pas pour l'instant. La section WITH n'est pas tr\u00e8s s\u00e9rieuse chez nous. C'est une petite fonctionnalit\u00e9.<\/p>\n<p><\/p>\n<p><em>J'ai compris. Merci !<\/em><\/p>\n<p><\/p>\n<p><em>Merci pour la pr\u00e9sentation ! C'\u00e9tait tr\u00e8s int\u00e9ressant ! Une question globale. Pr\u00e9voyez-vous de faire, peut-\u00eatre sous forme de quelques placeholders, une modification pour la suppression de donn\u00e9es ?<\/em><\/p>\n<p><\/p>\n<p>C'est s\u00fbr. C'est notre premi\u00e8re t\u00e2che dans notre file d'attente. Nous avons actuellement r\u00e9fl\u00e9chi de mani\u00e8re active \u00e0 la mani\u00e8re de tout faire correctement. Il est temps de commencer \u00e0 frapper sur le clavier*.<\/p>\n<p><\/p>\n<p>*Nous avons appuy\u00e9 sur les touches du clavier et tout est fait.<\/p>\n<p><\/p>\n<p><em>Cela va-t-il affecter la performance du syst\u00e8me ou non ? L'insertion sera-t-elle aussi rapide qu'actuellement ?<\/em><\/p>\n<p><\/p>\n<p>Il est possible que les suppressions et les mises \u00e0 jour soient tr\u00e8s lourdes, mais cela n'affectera pas les performances des s\u00e9lections et des insertions.<\/p>\n<p><\/p>\n<p><em>Et une petite question. Lors de la pr\u00e9sentation, vous avez parl\u00e9 de la cl\u00e9 primaire. Donc, nous avons un partitionnement qui est par d\u00e9faut mensuel, n'est-ce pas ? Et quand nous sp\u00e9cifions une plage de dates qui rentre dans le mois, seule cette partition est lue, c'est bien \u00e7a ?<\/em><\/p>\n<p><\/p>\n<p>Oui.<\/p>\n<p><\/p>\n<p><em>Une question. Si nous ne pouvons pas \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c de cl\u00e9 primaire, est-il correct de la faire sur le champ \u00ab Date \u00bb afin de r\u00e9duire la r\u00e9organisation des donn\u00e9es en arri\u00e8re-plan pour qu'elles soient mieux ordonn\u00e9es ? Si vous n'avez pas de requ\u00eates par plages et que vous ne pouvez pas choisir de cl\u00e9 primaire, vaut-il mieux mettre la date en cl\u00e9 primaire ?<\/em><\/p>\n<p><\/p>\n<p>Oui.<\/p>\n<p><\/p>\n<p>Peut-\u00eatre que cela vaut la peine d'inclure dans la cl\u00e9 primaire un champ qui permettra une meilleure compression des donn\u00e9es si elles sont tri\u00e9es par celui-ci. Par exemple, l'identifiant d'un utilisateur. Un utilisateur, par exemple, visite le m\u00eame site. Dans ce cas, vous mettez l'identifiant de l'utilisateur et le temps. Ainsi, vos donn\u00e9es seront mieux compress\u00e9es. Concernant la date, si vous n'avez vraiment jamais de requ\u00eates par plages de dates, il n'est pas n\u00e9cessaire d'inclure la date dans la cl\u00e9 primaire. <\/p>\n<p><\/p>\n<p><em>Bien, merci beaucoup !<\/em><\/p>\n<p>Source : <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.2 - 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\/fr\/blog\/administrirovanie\/effektivnoe-ispolzovanie-clickhouse-aleksej-milovidov-yandeks\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"fr_FR\" \/>\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\/fr\/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\udd47Utilisation efficace de ClickHouse. Alexey Milovidov (Yandex) | ProHoster","description":"","canonical_url":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/effektivnoe-ispolzovanie-clickhouse-aleksej-milovidov-yandeks","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"fr_FR","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\/fr\/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\/fr\/wp-json\/wp\/v2\/posts\/91438","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/comments?post=91438"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts\/91438\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/media\/91439"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/media?parent=91438"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/categories?post=91438"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/tags?post=91438"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}