{"id":74737,"date":"2020-03-20T08:43:14","date_gmt":"2020-03-20T05:43:14","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/optimizacziya-strok-v-clickhouse-doklad-yandeksa"},"modified":"2020-03-20T08:43:14","modified_gmt":"2020-03-20T05:43:14","slug":"optimizacziya-strok-v-clickhouse-doklad-yandeksa","status":"publish","type":"post","link":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/optimizacziya-strok-v-clickhouse-doklad-yandeksa","title":{"rendered":"Optimisation des cha\u00eenes dans ClickHouse. Pr\u00e9sentation de Yandex.","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>La base de donn\u00e9es analytique ClickHouse traite de nombreuses cha\u00eenes diff\u00e9rentes, consommant des ressources. Pour acc\u00e9l\u00e9rer le fonctionnement du syst\u00e8me, de nouvelles optimisations sont constamment ajout\u00e9es. Le d\u00e9veloppeur de ClickHouse, Nikolai Kochetov, parle du type de donn\u00e9es string, y compris d'un nouveau type, LowCardinality, et explique comment acc\u00e9l\u00e9rer le traitement des cha\u00eenes. <\/p>\n<p><center><div class=\"youtube-placeholder\" data-id=\"rqf-ILRgBdY\" onclick=\"loadVideo(this)\">\r\n        <img decoding=\"async\" src=\"https:\/\/img.youtube.com\/vi\/rqf-ILRgBdY\/hqdefault.jpg\" alt=\"Lire la vid\u00e9o\" loading=\"lazy\" width=\"480\" height=\"360\" style=\"width:100%;height:auto;\">\r\n        <div class=\"play-button\"><\/div>\r\n    <\/div><\/center><br \/>\n\u2014 Commen\u00e7ons par comprendre comment stocker les cha\u00eenes. <br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><br \/>\n<img decoding=\"async\" alt=\"Optimisation des cha\u00eenes dans ClickHouse. Pr\u00e9sentation de Yandex.\" src=\"\/wp-content\/uploads\/2020\/03\/5e38e903aaaf54a533bd3026e76a14be.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nNous avons des types de donn\u00e9es string. String convient comme valeur par d\u00e9faut, il est presque toujours pr\u00e9f\u00e9rable de l'utiliser. Il a un faible Overhead \u2014 9 octets par cha\u00eene. Si nous voulons que la taille des cha\u00eenes soit fixe et connue \u00e0 l'avance, il vaut mieux utiliser FixedString. Dans ce type, nous pouvons d\u00e9finir le nombre d'octets souhait\u00e9, ce qui est pratique pour les donn\u00e9es comme les adresses IP ou les fonctions de hachage. <\/p>\n<p><img decoding=\"async\" alt=\"Optimisation des cha\u00eenes dans ClickHouse. Pr\u00e9sentation de Yandex.\" src=\"\/wp-content\/uploads\/2020\/03\/eaae898fb5163cb1c070c34a13f6f160.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nBien s\u00fbr, parfois quelque chose ralentit. Supposons que vous fassiez une requ\u00eate \u00e0 une table. ClickHouse lit une quantit\u00e9 assez importante de donn\u00e9es, disons \u00e0 une vitesse de 100 Go\/s, tout en traitant peu de cha\u00eenes. Nous avons deux tables qui stockent presque les m\u00eames donn\u00e9es. ClickHouse lit les donn\u00e9es de la deuxi\u00e8me table \u00e0 une vitesse plus \u00e9lev\u00e9e, mais le nombre de cha\u00eenes lues par seconde est trois fois inf\u00e9rieur. <\/p>\n<p><img decoding=\"async\" alt=\"Optimisation des cha\u00eenes dans ClickHouse. Pr\u00e9sentation de Yandex.\" src=\"\/wp-content\/uploads\/2020\/03\/be7cc47e628112bb212ed0e8ff9091ed.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nSi nous regardons la taille des donn\u00e9es compress\u00e9es, elle sera presque \u00e9quivalente. En r\u00e9alit\u00e9, les m\u00eames donn\u00e9es sont enregistr\u00e9es dans les tables \u2014 le premier milliard de nombres \u2014 seulement dans la premi\u00e8re colonne, elles sont enregistr\u00e9es sous forme de UInt64, tandis que dans la seconde, elles sont sous forme de String. \u00c0 cause de cela, la deuxi\u00e8me requ\u00eate met plus de temps \u00e0 lire les donn\u00e9es depuis le disque et \u00e0 les d\u00e9compresser. <\/p>\n<p><img decoding=\"async\" alt=\"Optimisation des cha\u00eenes dans ClickHouse. Pr\u00e9sentation de Yandex.\" src=\"\/wp-content\/uploads\/2020\/03\/c699103cecd972fcee73841cc35716d6.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nVoici un autre exemple. Supposons qu'il y ait un ensemble de cha\u00eenes connu \u00e0 l'avance, limit\u00e9 par une constante de 1000 ou 10 000 et qui ne change presque jamais. Dans ce cas, le type de donn\u00e9es Enum est appropri\u00e9, ClickHouse en propose deux \u2014 Enum8 et Enum16. Gr\u00e2ce au stockage sous Enum, nous traitons rapidement les requ\u00eates. <\/p>\n<p>ClickHouse dispose d'acc\u00e9l\u00e9rations pour GROUP BY, IN, DISTINCT et d'optimisations pour certaines fonctions, par exemple pour la comparaison avec une cha\u00eene constante. Bien s\u00fbr, les nombres dans la cha\u00eene ne sont pas convertis, au contraire, la cha\u00eene constante est convertie en valeur Enum. Apr\u00e8s cela, tout se compare rapidement. <\/p>\n<p>Mais il y a aussi des inconv\u00e9nients. M\u00eame si nous connaissons pr\u00e9cis\u00e9ment l'ensemble des cha\u00eenes, il doit parfois \u00eatre compl\u00e9t\u00e9. Une nouvelle cha\u00eene arrive \u2014 nous devons effectuer un ALTER. <\/p>\n<p><img decoding=\"async\" alt=\"Optimisation des cha\u00eenes dans ClickHouse. Pr\u00e9sentation de Yandex.\" src=\"\/wp-content\/uploads\/2020\/03\/064c35faaf3d9de2f12d29f83197e983.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nL'ALTER pour Enum dans ClickHouse est r\u00e9alis\u00e9 de mani\u00e8re optimale. Nous ne r\u00e9\u00e9crivons pas les donn\u00e9es sur le disque, mais l'ALTER peut ralentir en raison du stockage des structures Enum dans le sch\u00e9ma m\u00eame de la table. Par cons\u00e9quent, nous devons attendre les requ\u00eates de lecture de la table, par exemple. <\/p>\n<p>La question se pose : peut-on faire mieux ? Probablement, oui. On peut conserver la structure Enum non pas dans le sch\u00e9ma de la table, mais dans ZooKeeper. Cependant, des probl\u00e8mes de synchronisation peuvent survenir. Par exemple, une r\u00e9plique a re\u00e7u des donn\u00e9es, l'autre non, et si elle poss\u00e8de une vieille Enum, alors quelque chose pourrait \u00e9chouer. (Dans ClickHouse, nous avons presque termin\u00e9 les requ\u00eates ALTER non bloquantes. Lorsque nous les terminerons enti\u00e8rement, il ne sera plus n\u00e9cessaire d'attendre les requ\u00eates de lecture.)<\/p>\n<p><img decoding=\"async\" alt=\"Optimisation des cha\u00eenes dans ClickHouse. Pr\u00e9sentation de Yandex.\" src=\"\/wp-content\/uploads\/2020\/03\/f5d2fdf14778f6afdd4acc8c204e163c.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPour \u00e9viter de s'emb\u00eater avec ALTER Enum, on peut utiliser des dictionnaires externes dans ClickHouse. Je rappelle que c'est une structure de donn\u00e9es cl\u00e9-valeur \u00e0 l'int\u00e9rieur de ClickHouse, qui permet d'obtenir des donn\u00e9es \u00e0 partir de sources externes, comme des tables MySQL. <\/p>\n<p>Dans le dictionnaire ClickHouse, nous stockons de nombreuses cha\u00eenes diff\u00e9rentes, et dans la table, leurs identifiants sous forme de nombres. Si nous devons obtenir une cha\u00eene, nous appelons la fonction dictGet et travaillons avec elle. Apr\u00e8s cela, nous n'avons plus besoin de faire ALTER. Pour ajouter quelque chose \u00e0 l'Enum, nous l'ins\u00e9rons dans la m\u00eame table MySQL. <\/p>\n<p>Mais cela pose d'autres probl\u00e8mes. Premi\u00e8rement, une syntaxe peu pratique. Si nous voulons obtenir une cha\u00eene, nous devons appeler dictGet. Deuxi\u00e8mement, l'absence de certaines optimisations. Comparer avec une cha\u00eene constante pour les dictionnaires n'est pas aussi rapide. <\/p>\n<p>Il peut \u00e9galement y avoir des probl\u00e8mes de mise \u00e0 jour. Supposons que nous ayons demand\u00e9 une cha\u00eene dans le dictionnaire cache, mais qu'elle n'y soit pas. Dans ce cas, nous devons attendre que les donn\u00e9es soient charg\u00e9es \u00e0 partir de la source externe. <\/p>\n<p><img decoding=\"async\" alt=\"Optimisation des cha\u00eenes dans ClickHouse. Pr\u00e9sentation de Yandex.\" src=\"\/wp-content\/uploads\/2020\/03\/534818ee523a243623a5cb2babe08040.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nLe principal inconv\u00e9nient des deux m\u00e9thodes est que nous stockons toutes les cl\u00e9s au m\u00eame endroit et les synchronisons. Alors, pourquoi ne pas stocker les dictionnaires localement ? Pas de synchronisation, pas de probl\u00e8me. On peut stocker le dictionnaire localement dans un morceau sur le disque. C'est-\u00e0-dire que nous avons fait un Insert, enregistr\u00e9 le dictionnaire. Si nous travaillons avec des donn\u00e9es en m\u00e9moire, nous pouvons enregistrer le dictionnaire soit dans un bloc de donn\u00e9es, soit dans un morceau de colonne, soit dans un cache, pour acc\u00e9l\u00e9rer les calculs.<\/p>\n<h3>Codage par dictionnaire des cha\u00eenes <\/h3>\n<p>\nAinsi, nous sommes arriv\u00e9s \u00e0 la cr\u00e9ation d'un nouveau type de donn\u00e9es dans ClickHouse \u2014 LowCardinality. C'est un format de stockage de donn\u00e9es : comment elles sont \u00e9crites sur le disque et comment elles sont lues, comment elles sont repr\u00e9sent\u00e9es en m\u00e9moire et leur sch\u00e9ma de traitement. <\/p>\n<p><img decoding=\"async\" alt=\"Optimisation des cha\u00eenes dans ClickHouse. Pr\u00e9sentation de Yandex.\" src=\"\/wp-content\/uploads\/2020\/03\/e25b2eb12ff158b89b7d2dbdfb8e2e5a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nLe diaporama comporte deux colonnes. \u00c0 droite, les cha\u00eenes sont standardis\u00e9es en type String. On peut voir qu'il s'agit de mod\u00e8les de t\u00e9l\u00e9phones mobiles. \u00c0 gauche, il y a une colonne identique, mais de type LowCardinality. Elle est compos\u00e9e d'un dictionnaire avec de nombreuses cha\u00eenes diff\u00e9rentes (les cha\u00eenes de la colonne de droite) et d'une liste de positions (num\u00e9ros de lignes). <\/p>\n<p>Avec ces deux structures, il est possible de restaurer la colonne d'origine. Il existe \u00e9galement un index invers\u00e9 \u2014 une table de hachage qui aide \u00e0 trouver la position dans le dictionnaire par la cha\u00eene. Cela est n\u00e9cessaire pour acc\u00e9l\u00e9rer certaines requ\u00eates. Par exemple, si nous voulons comparer, rechercher une cha\u00eene dans notre colonne ou les fusionner. <\/p>\n<p>LowCardinality est un type de donn\u00e9es param\u00e9trique. Il peut \u00eatre soit un nombre, soit quelque chose stock\u00e9 sous forme de nombre, soit une cha\u00eene, soit Nullable de ceux-ci. <\/p>\n<p><img decoding=\"async\" alt=\"Optimisation des cha\u00eenes dans ClickHouse. Pr\u00e9sentation de Yandex.\" src=\"\/wp-content\/uploads\/2020\/03\/d52ef0c99617238442d4f71e43af48af.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nLa particularit\u00e9 de LowCardinality est qu'il peut \u00eatre conserv\u00e9 pour certaines fonctions. Dans le diaporama, un exemple de requ\u00eate est montr\u00e9. Dans la premi\u00e8re ligne, j'ai cr\u00e9\u00e9 une colonne de type LowCardinality \u00e0 partir de String, que j'ai nomm\u00e9e S. Ensuite, j'ai demand\u00e9 son nom \u2014 ClickHouse a indiqu\u00e9 que c'est LowCardinality de String. C'est correct.<\/p>\n<p>La troisi\u00e8me ligne est presque la m\u00eame, sauf que nous avons appel\u00e9 la fonction length. Dans ClickHouse, la fonction length renvoie le type de donn\u00e9es UInt64. Mais nous avons obtenu LowCardinality de UInt64. Quel est le sens ?<\/p>\n<p><img decoding=\"async\" alt=\"Optimisation des cha\u00eenes dans ClickHouse. Pr\u00e9sentation de Yandex.\" src=\"\/wp-content\/uploads\/2020\/03\/a4a51a0f1ecd68f7fffd521ab786c8a5.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDans le dictionnaire \u00e9taient stock\u00e9s les noms de t\u00e9l\u00e9phones mobiles, nous avons appliqu\u00e9 la fonction length. Nous avons maintenant un dictionnaire similaire, compos\u00e9 uniquement de nombres \u2014 ce sont les longueurs des cha\u00eenes. La colonne avec les positions n'a pas chang\u00e9. Au final, nous avons trait\u00e9 moins de donn\u00e9es, \u00e9conomisant ainsi du temps de requ\u00eate. <\/p>\n<p>Il peut y avoir d'autres optimisations, telles que l'ajout d'un cache simple. Lors du calcul de la valeur d'une fonction, il est possible de s'en souvenir et de composer une identique sans avoir \u00e0 recalculer. <\/p>\n<p>Une optimisation GROUP BY peut \u00e9galement \u00eatre effectu\u00e9e, car notre colonne avec le dictionnaire est d\u00e9j\u00e0 partiellement agr\u00e9g\u00e9e \u2014 cela permet de calculer plus rapidement les valeurs des fonctions de hachage et de trouver approximativement le bucket o\u00f9 ins\u00e9rer la prochaine ligne. De plus, certaines fonctions d'agr\u00e9gation peuvent \u00eatre sp\u00e9cialis\u00e9es, par exemple uniq, car elle peut recevoir uniquement le dictionnaire, laissant les positions intactes \u2014 tout cela fonctionnera plus rapidement. Les deux premi\u00e8res optimisations ont d\u00e9j\u00e0 \u00e9t\u00e9 ajout\u00e9es dans ClickHouse.<\/p>\n<p><img decoding=\"async\" alt=\"Optimisation des cha\u00eenes dans ClickHouse. Pr\u00e9sentation de Yandex.\" src=\"\/wp-content\/uploads\/2020\/03\/943e0a8ae5a37cd47164246db3a67893.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nQue se passerait-il si nous cr\u00e9ions une colonne avec notre type de donn\u00e9es et y ins\u00e9rions de nombreuses cha\u00eenes de caract\u00e8res diff\u00e9rentes et non conformes ? La m\u00e9moire ne va-t-elle pas d\u00e9border ? Non, pour cela, ClickHouse dispose de deux configurations sp\u00e9ciales. La premi\u00e8re est low_cardinality_max_dictionary_size. C'est la taille maximale du dictionnaire qui peut \u00eatre \u00e9crit sur le disque. L'insertion se d\u00e9roule comme suit : lorsque nous ins\u00e9rons des donn\u00e9es, un flux de cha\u00eenes de caract\u00e8res nous parvient, \u00e0 partir duquel nous formons un grand dictionnaire commun. Si le dictionnaire devient plus grand que la valeur de la configuration, nous \u00e9crivons le dictionnaire actuel sur le disque, et les autres cha\u00eenes sont \u00ab mises de c\u00f4t\u00e9 \u00bb, \u00e0 c\u00f4t\u00e9 des index. Au final, nous ne recalculons jamais un grand dictionnaire et ne rencontrons pas de probl\u00e8mes de m\u00e9moire. <\/p>\n<p>La deuxi\u00e8me configuration s'appelle low_cardinality_use_single_dictionary_for_part. Imaginez que dans le sch\u00e9ma pr\u00e9c\u00e9dent, lorsque nous ins\u00e9rions des donn\u00e9es, notre dictionnaire a d\u00e9bord\u00e9 et que nous l'avons \u00e9crit sur le disque. La question se pose : pourquoi ne pas maintenant former un autre dictionnaire identique ? <\/p>\n<p>Lorsqu'il d\u00e9bordera, nous l'\u00e9crirons \u00e0 nouveau sur le disque et commencerons \u00e0 former un troisi\u00e8me. Cette configuration d\u00e9sactive par d\u00e9faut une telle possibilit\u00e9. <\/p>\n<p>En fait, avoir plusieurs dictionnaires peut \u00eatre utile si nous voulons ins\u00e9rer un certain nombre de cha\u00eenes de caract\u00e8res, mais que nous avons accidentellement ins\u00e9r\u00e9 des \u00ab d\u00e9chets \u00bb. Disons que nous avons d'abord ins\u00e9r\u00e9 des cha\u00eenes de mauvaise qualit\u00e9, puis de bonnes. Dans ce cas, le dictionnaire se divisera en plusieurs petits dictionnaires. Certains d'entre eux contiendront des \u00ab d\u00e9chets \u00bb, mais les derniers contiendront de bonnes cha\u00eenes. Et si nous lisons, disons, seulement le dernier fragment, cela fonctionnera \u00e9galement rapidement. <\/p>\n<p><img decoding=\"async\" alt=\"Optimisation des cha\u00eenes dans ClickHouse. Pr\u00e9sentation de Yandex.\" src=\"\/wp-content\/uploads\/2020\/03\/834ba3295ace98870334aa10a78e4781.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nAvant de parler des avantages de LowCardinality, je dois dire tout de suite que nous ne r\u00e9ussirons probablement pas \u00e0 r\u00e9duire les donn\u00e9es sur le disque (bien que cela puisse se produire), car ClickHouse compresse les donn\u00e9es. Il existe une option par d\u00e9faut : LZ4. Il est \u00e9galement possible de compresser par ZSTD. Mais les deux algorithmes impl\u00e9mentent d\u00e9j\u00e0 la compression par dictionnaire, donc notre dictionnaire externe ClickHouse n'aidera pas vraiment. <\/p>\n<p>Pour ne pas \u00eatre accus\u00e9 de dire des b\u00eatises, j'ai pris certaines donn\u00e9es de la m\u00e9trique \u2014 String, LowCardinality(String) et Enum \u2014 et je les ai enregistr\u00e9es dans diff\u00e9rents types de donn\u00e9es. Cela a donn\u00e9 trois colonnes, contenant un milliard de lignes. Dans la premi\u00e8re colonne, CodePage, il y a seulement 62 valeurs. On voit que dans LowCardinality(String), nous avons mieux compress\u00e9. String est un peu moins performant, mais c'est probablement d\u00fb au fait que les cha\u00eenes sont courtes, nous stockons leurs longueurs, et elles prennent beaucoup de place, se compressent mal. <\/p>\n<p>Concernant PhoneModel, il y en a 48 000 \u2014 d\u00e9j\u00e0 plus, et les diff\u00e9rences entre String et LowCardinality(String) sont presque inexistantes. Pour les URL, nous avons \u00e9galement \u00e9conomis\u00e9 seulement 2 Go \u2014 je pense qu'il ne faut pas trop compter l\u00e0-dessus. <\/p>\n<h3>\u00c9valuation de la vitesse de traitement<\/h3>\n<p>\n<img decoding=\"async\" alt=\"Optimisation des cha\u00eenes dans ClickHouse. Pr\u00e9sentation de Yandex.\" src=\"\/wp-content\/uploads\/2020\/03\/0b646570639f8f2e29b599473b84e25c.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<b><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/toddwschneider\/nyc-taxi-data\">Lien depuis la diapositive<\/a><\/noindex><\/b><\/p>\n<p>\u00c9valuons maintenant la vitesse de traitement. Pour cela, j'ai utilis\u00e9 un ensemble de donn\u00e9es sur les trajets de taxi \u00e0 New York. Il <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/toddwschneider\/nyc-taxi-data\">disponible<\/a><\/noindex> se trouve sur GitHub. Il contient un peu plus d'un milliard de trajets. Il refl\u00e8te la localisation, l'heure de d\u00e9part et de fin du trajet, le mode de paiement, le nombre de passagers et m\u00eame le type de taxi \u2014 vert, jaune et Uber. <\/p>\n<p><img decoding=\"async\" alt=\"Optimisation des cha\u00eenes dans ClickHouse. Pr\u00e9sentation de Yandex.\" src=\"\/wp-content\/uploads\/2020\/03\/0901669dec01b0f956d6976e3aa8b741.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nJ'ai commenc\u00e9 par une requ\u00eate assez simple \u2014 j'ai demand\u00e9 o\u00f9 les taxis sont command\u00e9s le plus souvent. Pour cela, il faut prendre la localisation d'o\u00f9 le taxi a \u00e9t\u00e9 command\u00e9, faire un GROUP BY sur celle-ci et compter avec la fonction count. Voici ce que ClickHouse retourne. <\/p>\n<p><img decoding=\"async\" alt=\"Optimisation des cha\u00eenes dans ClickHouse. Pr\u00e9sentation de Yandex.\" src=\"\/wp-content\/uploads\/2020\/03\/50983341e20bcbc1b5adbaed35f8624d.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPour mesurer la vitesse de traitement de la requ\u00eate, j'ai cr\u00e9\u00e9 trois tables avec les m\u00eames donn\u00e9es, mais j'ai utilis\u00e9 pour notre localisation de d\u00e9part trois types de donn\u00e9es diff\u00e9rents \u2014 String, LowCardinality et Enum. LowCardinality et Enum se sont r\u00e9v\u00e9l\u00e9s cinq fois plus rapides que String. Enum est plus rapide car il fonctionne avec des chiffres. LowCardinality \u2014 car une optimisation GROUP BY a \u00e9t\u00e9 mise en \u0153uvre. <\/p>\n<p><img decoding=\"async\" alt=\"Optimisation des cha\u00eenes dans ClickHouse. Pr\u00e9sentation de Yandex.\" src=\"\/wp-content\/uploads\/2020\/03\/e2ce4f2127d8728287488c85c92085fc.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nRendons la requ\u00eate un peu plus complexe \u2014 demandons o\u00f9 se trouve le parc le plus populaire \u00e0 New York. Encore une fois, nous allons le mesurer en fonction des endroits o\u00f9 les taxis sont le plus souvent command\u00e9s, mais en filtrant uniquement les localisations contenant le mot \u00ab parc \u00bb. Nous ajouterons \u00e9galement la fonction like. <\/p>\n<p><img decoding=\"async\" alt=\"Optimisation des cha\u00eenes dans ClickHouse. Pr\u00e9sentation de Yandex.\" src=\"\/wp-content\/uploads\/2020\/03\/7cf6fd64751f3ae578581caddde17aaf.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nRegardons le temps \u2014 nous voyons qu'Enum a soudainement commenc\u00e9 \u00e0 ralentir. Il fonctionne m\u00eame plus lentement que le type de donn\u00e9es standard String. Cela se produit parce que la fonction like n'est pas du tout optimis\u00e9e pour Enum. Nous devons convertir nos cha\u00eenes d'Enum en cha\u00eenes ordinaires \u2014 cela alourdit notre travail. LowCardinality(String) n'est pas non plus optimis\u00e9 par d\u00e9faut, mais dans ce cas, like fonctionne sur le dictionnaire, donc la requ\u00eate est acc\u00e9l\u00e9r\u00e9e par rapport \u00e0 String. <\/p>\n<p>Lors de l'utilisation d'Enum, il existe un probl\u00e8me plus global. Si nous voulons l'optimiser, nous devons le faire \u00e0 chaque endroit dans le code. Supposons que nous ayons \u00e9crit une nouvelle fonction - il est imp\u00e9ratif de penser \u00e0 une optimisation pour Enum. En revanche, LowCardinality est optimis\u00e9 par d\u00e9faut.<\/p>\n<p><img decoding=\"async\" alt=\"Optimisation des cha\u00eenes dans ClickHouse. Pr\u00e9sentation de Yandex.\" src=\"\/wp-content\/uploads\/2020\/03\/459243eb5b3dd993393d0184b224ea09.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nExaminons la derni\u00e8re requ\u00eate, plus artificielle. Nous allons simplement calculer la fonction de hachage de notre emplacement. La fonction de hachage est une requ\u00eate assez lente, elle prend du temps \u00e0 calculer, donc tout sera retard\u00e9 d'environ trois fois.<\/p>\n<p><img decoding=\"async\" alt=\"Optimisation des cha\u00eenes dans ClickHouse. Pr\u00e9sentation de Yandex.\" src=\"\/wp-content\/uploads\/2020\/03\/a5f49c22748971646ec358eb52d3feda.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nLowCardinality fonctionne encore plus rapidement, bien qu'il n'y ait pas de filtrage. Cela est d\u00fb au fait que nos fonctions ne travaillent que sur le dictionnaire. La fonction de calcul de hachage a un argument - elle peut traiter moins de donn\u00e9es et peut \u00e9galement renvoyer LowCardinality. <\/p>\n<p><img decoding=\"async\" alt=\"Optimisation des cha\u00eenes dans ClickHouse. Pr\u00e9sentation de Yandex.\" src=\"\/wp-content\/uploads\/2020\/03\/7842b7eb2debb4a4b1d4cbc3488deb32.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nNotre objectif global est d'atteindre une vitesse de fonctionnement \u00e9quivalente \u00e0 celle de String dans tous les cas, tout en conservant les am\u00e9liorations. Et, peut-\u00eatre, un jour, nous remplacerons String par LowCardinality, vous mettrez \u00e0 jour ClickHouse, et tout fonctionnera un peu plus vite.<br \/>\n<br \/>Source : <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/yandex\/blog\/492868\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0410\u043d\u0430\u043b\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0421\u0423\u0411\u0414 ClickHouse \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0440\u0430\u0437\u043d\u044b\u0445 \u0441\u0442\u0440\u043e\u043a, \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u044f\u044f \u0440\u0435\u0441\u0443\u0440\u0441\u044b. \u0414\u043b\u044f \u0443\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043d\u043e\u0432\u044b\u0435 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438. \u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a ClickHouse \u041d\u0438\u043a\u043e\u043b\u0430\u0439 \u041a\u043e\u0447\u0435\u0442\u043e\u0432 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043e \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u043e\u043c \u0442\u0438\u043f\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u043e \u043d\u043e\u0432\u043e\u043c \u0442\u0438\u043f\u0435, LowCardinality, \u0438 \u043e\u0431\u044a\u044f\u0441\u043d\u044f\u0435\u0442, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0443\u0441\u043a\u043e\u0440\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u0441\u043e \u0441\u0442\u0440\u043e\u043a\u0430\u043c\u0438. \u2014 \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c\u0441\u044f, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0438. \u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u044b\u0435 \u0442\u0438\u043f\u044b \u0434\u0430\u043d\u043d\u044b\u0445. [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":74738,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-74737","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=\"description\" content=\"\u0410\u043d\u0430\u043b\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0421\u0423\u0411\u0414 ClickHouse \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0440\u0430\u0437\u043d\u044b\u0445 \u0441\u0442\u0440\u043e\u043a, \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u044f\u044f \u0440\u0435\u0441\u0443\u0440\u0441\u044b. \u0414\u043b\u044f \u0443\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043d\u043e\u0432\u044b\u0435 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438.\" \/>\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\/optimizacziya-strok-v-clickhouse-doklad-yandeksa\" \/>\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\u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u0442\u0440\u043e\u043a \u0432 ClickHouse. \u0414\u043e\u043a\u043b\u0430\u0434 \u042f\u043d\u0434\u0435\u043a\u0441\u0430 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0410\u043d\u0430\u043b\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0421\u0423\u0411\u0414 ClickHouse \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0440\u0430\u0437\u043d\u044b\u0445 \u0441\u0442\u0440\u043e\u043a, \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u044f\u044f \u0440\u0435\u0441\u0443\u0440\u0441\u044b. \u0414\u043b\u044f \u0443\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043d\u043e\u0432\u044b\u0435 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/optimizacziya-strok-v-clickhouse-doklad-yandeksa\" \/>\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-03-20T05:43:14+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-03-20T05:43:14+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\udd47Optimisation des cha\u00eenes dans ClickHouse. Pr\u00e9sentation de Yandex | ProHoster","description":"La base de donn\u00e9es analytique ClickHouse traite de nombreuses cha\u00eenes diff\u00e9rentes, consommant des ressources. Pour acc\u00e9l\u00e9rer le fonctionnement du syst\u00e8me, de nouvelles optimisations sont constamment ajout\u00e9es.","canonical_url":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/optimizacziya-strok-v-clickhouse-doklad-yandeksa","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\u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u0442\u0440\u043e\u043a \u0432 ClickHouse. \u0414\u043e\u043a\u043b\u0430\u0434 \u042f\u043d\u0434\u0435\u043a\u0441\u0430 | ProHoster","og:description":"\u0410\u043d\u0430\u043b\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0421\u0423\u0411\u0414 ClickHouse \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0440\u0430\u0437\u043d\u044b\u0445 \u0441\u0442\u0440\u043e\u043a, \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u044f\u044f \u0440\u0435\u0441\u0443\u0440\u0441\u044b. \u0414\u043b\u044f \u0443\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043d\u043e\u0432\u044b\u0435 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438.","og:url":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/optimizacziya-strok-v-clickhouse-doklad-yandeksa","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-03-20T05:43:14+00:00","article:modified_time":"2020-03-20T05:43:14+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"74737","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 17:23:10","updated":"2022-09-27 14:48:44","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\/74737","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=74737"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts\/74737\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/media\/74738"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/media?parent=74737"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/categories?post=74737"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/tags?post=74737"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}