{"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\/de\/blog\/administrirovanie\/effektivnoe-ispolzovanie-clickhouse-aleksej-milovidov-yandeks","title":{"rendered":"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/8e42c1fffffcc964eacef240ea90bbc5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Da ClickHouse ein spezialisiertes System ist, ist es beim Einsatz wichtig, die Besonderheiten seiner Architektur zu ber\u00fccksichtigen. In diesem Bericht wird Alexej Beispiele typischer Fehler beim Einsatz von ClickHouse vorstellen, die zu einer ineffizienten Nutzung f\u00fchren k\u00f6nnen. An praktischen Beispielen wird gezeigt, wie die Wahl einer bestimmten Datenschema die Leistung erheblich ver\u00e4ndern kann.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Hallo zusammen! Mein Name ist Alexej, ich arbeite mit ClickHouse.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/7f5fc01663be58d3d25e518a4169b8cf.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Zun\u00e4chst m\u00f6chte ich euch erfreuen, dass ich euch heute nicht erz\u00e4hlen werde, was ClickHouse ist. Ehrlich gesagt, ich habe genug davon. Ich erkl\u00e4re immer wieder, was es ist. Und wahrscheinlich wissen es schon alle. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/fae6bd07d098200643d591b8e5bf51e8.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Stattdessen werde ich dar\u00fcber sprechen, welche m\u00f6glichen Stolpersteine es gibt, d. h. wie man ClickHouse falsch benutzen kann. Tats\u00e4chlich braucht man keine Angst zu haben, denn wir entwickeln ClickHouse als ein System, das einfach, benutzerfreundlich ist und sofort funktioniert. Man installiert es und fertig, keine Probleme. <\/p>\n<p><\/p>\n<p>Es ist jedoch zu beachten, dass dieses System spezialisiert ist und man leicht auf ungew\u00f6hnliche Nutzungsszenarien sto\u00dfen kann, die das System aus der Komfortzone bringen.<\/p>\n<p><\/p>\n<p>Also, welche Stolpersteine gibt es? Ich werde haupts\u00e4chlich \u00fcber offensichtliche Dinge sprechen. Allen ist alles offensichtlich, alle verstehen alles und k\u00f6nnen sich freuen, dass sie so clever sind, w\u00e4hrend diejenigen, die es nicht verstehen, etwas Neues erfahren werden. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/bffacf353ff31b361460178e911f0e16.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ein ganz einfaches Beispiel, das leider h\u00e4ufig vorkommt, ist die gro\u00dfe Anzahl an Inserts mit kleinen Batches, d. h. eine gro\u00dfe Anzahl kleiner Inserts.<\/p>\n<p><\/p>\n<p>Wenn man sich ansieht, wie ClickHouse Inserts ausf\u00fchrt, kann man mit einem einzigen Befehl auch einen Datenstrom von einem Terabyte senden. Das ist kein Problem. <\/p>\n<p><\/p>\n<p>Schauen wir uns die typische Leistung an. Zum Beispiel haben wir eine Tabelle mit Daten aus Yandex.Metrica. Hits. 105 irgendwelche Spalten. 700 Bytes im unkomprimierten Zustand. Und wir werden ordentliche Batches mit einer Million Zeilen einf\u00fcgen. <\/p>\n<p><\/p>\n<p>Wir f\u00fcgen in die MergeTree-Tabelle ein, und es ergibt sich eine halbe Million Zeilen pro Sekunde. Hervorragend. In der replizierten Tabelle wird es etwas weniger, etwa 400.000 Zeilen pro Sekunde. <\/p>\n<p><\/p>\n<p>Wenn man die Quorum-Insertion einschaltet, erh\u00e4lt man etwas weniger, aber immer noch eine respektable Leistung, 250.000 Zeilen pro Sekunde. Die Quorum-Insertion ist eine undocumented feature in ClickHouse*.<\/p>\n<p><\/p>\n<p>* Stand 2020, <noindex><a rel=\"nofollow\" href=\"https:\/\/clickhouse.tech\/docs\/en\/operations\/settings\/settings\/#settings-insert_quorum\">bereits dokumentiert.<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/668498fc82a0f6e851d05e6e1ea67033.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Was passiert, wenn man es schlecht macht? Wir f\u00fcgen eine Zeile nach der anderen in die MergeTree-Tabelle ein, und es entstehen 59 Zeilen pro Sekunde. Das ist 10.000 Mal langsamer. Beim ReplicatedMergeTree sind es 6 Zeilen pro Sekunde. Wenn dann noch ein Quorum aktiviert wird, sind es nur 2 Zeilen pro Sekunde. Meiner Meinung nach ist das einfach unertr\u00e4glich. Wie kann man so tr\u00e4ge sein? Sogar auf meinem T-Shirt steht, dass ClickHouse nicht tr\u00e4ge sein sollte. Aber trotzdem passiert es manchmal. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/4c771eddc4e8453f60ef91123ae5d109.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Tats\u00e4chlich ist das unser Fehler. Wir h\u00e4tten es problemlos so einrichten k\u00f6nnen, dass alles normal funktioniert, aber wir haben es nicht getan. Und wir haben es nicht getan, weil es f\u00fcr unser Szenario nicht erforderlich war. Wir hatten bereits Chargen. Daten wurden einfach in Chargen zu uns eingespielt, und es gab keine Probleme. Wir f\u00fcgen ein, und alles funktioniert normal. Aber nat\u00fcrlich sind verschiedene Szenarien m\u00f6glich. Zum Beispiel, wenn Sie eine Reihe von Servern haben, auf denen Daten generiert werden. Und sie f\u00fcgen Daten nicht so oft ein, aber es gibt trotzdem h\u00e4ufige Einf\u00fcgungen. Und das muss man irgendwie vermeiden. <\/p>\n<p><\/p>\n<p>Technisch gesehen besteht das Problem darin, dass, wenn Sie einen Insert in ClickHouse durchf\u00fchren, die Daten nicht in eine Memtable gelangen. Wir haben nicht einmal einen echten log structure MergeTree, sondern einfach nur einen MergeTree, weil es kein Log und keine MemTable gibt. Wir schreiben die Daten sofort in das Dateisystem, bereits nach Spalten sortiert. Und wenn Sie 100 Spalten haben, m\u00fcssen mehr als 200 Dateien in ein separates Verzeichnis geschrieben werden. Das ist ziemlich unhandlich. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/24688fe3d39d81b92f12ac1b8b21425b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Und die Frage stellt sich: \u201eWie macht man es richtig?\u201c, wenn eine solche Situation entsteht, dass man die Daten dennoch irgendwie in ClickHouse einf\u00fcgen muss.<\/p>\n<p><\/p>\n<p>Methode 1. Das ist die einfachste Methode. Verwenden Sie irgendeine verteilte Warteschlange. Zum Beispiel Kafka. Sie nehmen einfach die Daten aus Kafka heraus, batchen einmal pro Sekunde. Und alles wird gut, Sie schreiben es ein, alles funktioniert normal. <\/p>\n<p><\/p>\n<p>Die Nachteile sind, dass Kafka ein weiteres unhandliches verteiltes System ist. Ich verstehe, wenn Sie bereits Kafka in Ihrem Unternehmen haben. Das ist gut, das ist praktisch. Aber wenn nicht, sollten Sie dreimal nachdenken, bevor Sie sich einen weiteren verteilten System in Ihr Projekt holen. Daher sollten Sie Alternativen in Betracht ziehen. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/4f687221e8c7443abf02fb002c4eba5b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Methode 2. Eine solche altmodische Alternative, die dabei sehr einfach ist. Sie haben einen Server, der Ihre Protokolle generiert. Er speichert Ihre Protokolle einfach in einer Datei. Und einmal pro Sekunde benennen wir diese Datei um und \u00f6ffnen eine neue. Und ein separates Skript, entweder per Cronjob oder ein Daemon, nimmt die \u00e4lteste Datei und schreibt sie in ClickHouse. Wenn man die Protokolle einmal pro Sekunde schreibt, funktioniert alles wunderbar. <\/p>\n<p><\/p>\n<p>Der Nachteil dieser Methode ist jedoch, dass, wenn Ihr Server, auf dem die Protokolle generiert werden, verschwindet, auch die Daten verschwinden.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/b4c28b6df87386c42b6908bdfccb6b90.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Methode 3. Es gibt eine weitere interessante Methode, die \u00fcberhaupt ohne tempor\u00e4re Dateien auskommt. Zum Beispiel haben Sie eine Art von Werbekreisel oder einen anderen interessanten Daemon, der Daten generiert. Sie k\u00f6nnen eine Sammlung von Daten direkt im Arbeitsspeicher, im Puffer, speichern. Und wenn eine bestimmte Zeit vergangen ist, legen Sie diesen Puffer beiseite, erstellen einen neuen, und in einem separaten Thread f\u00fcgen Sie die bereits angesammelten Daten in ClickHouse ein.<\/p>\n<p><\/p>\n<p>Andererseits verschwinden die Daten auch bei einem kill -9. Wenn Ihr Server abst\u00fcrzt, verlieren Sie diese Daten. Ein weiteres Problem ist, dass, wenn Sie nicht in die Datenbank schreiben k\u00f6nnen, die Daten im Arbeitsspeicher angesammelt werden. Entweder l\u00e4uft der Arbeitsspeicher voll, oder Sie verlieren einfach die Daten. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/dc375b22fcb26cfa111d0bdb4563aa88.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Methode 4. Noch eine interessante Methode. Sie haben irgendeinen Serverprozess. Und er kann Daten sofort an ClickHouse senden, aber das in einer einzelnen Verbindung. Zum Beispiel senden Sie eine HTTP-Anfrage mit transfer-encoding: chunked mit einem Insert. Und er generiert die Chunks nicht zu selten, Sie k\u00f6nnen jede Zeile senden, obwohl es Overhead f\u00fcr das Framing dieser Daten geben wird. <\/p>\n<p><\/p>\n<p>Nichtsdestotrotz werden in diesem Fall die Daten sofort an ClickHouse gesendet. Und ClickHouse wird sie selbst puffern. <\/p>\n<p><\/p>\n<p>Aber auch hier treten Probleme auf. Jetzt verlieren Sie Daten auch dann, wenn Ihr Prozess abst\u00fcrzt, und, wenn der ClickHouse-Prozess abst\u00fcrzt, weil dies einen unvollendeten Insert bedeutet. In ClickHouse sind Inserts atomar bis zu einem bestimmten angegebenen Schwellenwert hinsichtlich der Zeilenanzahl. Prinzipiell ist das eine interessante Methode. Kann ebenfalls verwendet werden.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/6a18a974b9600ade377a870390e95d3d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Methode 5. Hier ist eine weitere interessante Methode. Dies ist ein von der Community entwickelter Server f\u00fcr das Batch-Processing von Daten. Ich habe mir das nicht selbst angeschaut, daher kann ich nichts garantieren. Allerdings werden auch f\u00fcr ClickHouse keine Garantien gegeben. Das ist ebenfalls Open Source, aber auf der anderen Seite haben Sie sich vielleicht an einen bestimmten Qualit\u00e4tsstandard gew\u00f6hnt, den wir zu liefern versuchen. F\u00fcr dieses Ding \u2013 ich wei\u00df nicht, schauen Sie auf GitHub vorbei, sehen Sie sich den Code an. Vielleicht haben sie etwas Brauchbares geschrieben. <\/p>\n<p><\/p>\n<p>* Stand 2020, sollte ebenfalls zur \u00dcberlegung hinzugef\u00fcgt werden <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=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/ae6a04af63ae4e7fa160c002fdb6d506.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Methode 6. Eine weitere M\u00f6glichkeit ist die Nutzung von Buffer-Tabellen. Der Vorteil dieser Methode ist, dass es sehr einfach ist, sie zu verwenden. Sie erstellen eine Buffer-Tabelle und f\u00fcgen Daten hinzu. <\/p>\n<p><\/p>\n<p>Der Nachteil ist, dass das Problem nicht vollst\u00e4ndig gel\u00f6st wird. Wenn Sie beim Einf\u00fcgen von MergeTree-Daten pro Sekunde ein Batch gruppieren m\u00fcssen, m\u00fcssen Sie beim Einf\u00fcgen in eine Buffer-Tabelle mindestens einige Tausend pro Sekunde gruppieren. Wenn es mehr als 10.000 pro Sekunde sind, wird es immer noch problematisch. Und wenn Sie in Batches einf\u00fcgen, sehen Sie, dass es dort Hunderttausende von Zeilen pro Sekunde gibt. Und das bereits mit relativ gro\u00dfen Daten. <\/p>\n<p><\/p>\n<p>Und auch Buffer-Tabellen haben kein Protokoll. Wenn mit Ihrem Server etwas nicht stimmt, gehen die Daten verloren. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/9bb16bf5e8145cc8368b11e54c86c837.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Und als Bonus haben wir k\u00fcrzlich die M\u00f6glichkeit hinzugef\u00fcgt, Daten aus Kafka abzurufen. Es gibt eine Tabellen-Engine \u2013 Kafka. Sie erstellen es einfach. Und dazu k\u00f6nnen Sie materialisierte Ansichten hinzuf\u00fcgen. In diesem Fall wird es die Daten selbst aus Kafka holen und in die ben\u00f6tigten Tabellen einf\u00fcgen. <\/p>\n<p><\/p>\n<p>Was mich besonders freut, ist, dass diese M\u00f6glichkeit nicht von uns erstellt wurde. Es ist ein Community-Feature. Und wenn ich \"Community-Feature\" sage, meine ich das ohne jegliche Abwertung. Wir haben den Code gelesen, Reviews gemacht, es sollte normal funktionieren. <\/p>\n<p><\/p>\n<p>* Stand 2020, gab es \u00e4hnliche Unterst\u00fctzung f\u00fcr <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=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/15dc61dfd435f5f8640395b7de480fe2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Was k\u00f6nnte beim Einf\u00fcgen von Daten unbequem oder unerwartet sein? Wenn Sie eine INSERT VALUES-Anfrage stellen und in den VALUES einige berechnete Ausdr\u00fccke schreiben. Zum Beispiel ist now() auch ein berechneter Ausdruck. Und in diesem Fall muss ClickHouse f\u00fcr jede Zeile den Interpreter dieser Ausdr\u00fccke ausf\u00fchren, und die Leistung wird dramatisch sinken. Es ist besser, dies zu vermeiden.<\/p>\n<p><\/p>\n<p>* Das Problem ist derzeit vollst\u00e4ndig gel\u00f6st, es gibt keine Leistungsverschlechterung mehr bei der Verwendung von Ausdr\u00fccken in VALUES.<\/p>\n<p><\/p>\n<p>Ein weiteres Beispiel f\u00fcr Probleme, die auftreten k\u00f6nnen, wenn in einem Batch Daten auf mehrere Partitionen verteilt sind. Standardm\u00e4\u00dfig partitioniert ClickHouse nach Monaten. Wenn Sie also einen Batch von einer Million Zeilen einf\u00fcgen und die Daten mehrere Jahre abdecken, haben Sie mehrere Dutzend Partitionen. Das entspricht der Tatsache, dass es in Wirklichkeit viele kleinere Batches gibt, da die Daten zun\u00e4chst nach Partitionen aufgeteilt werden.<\/p>\n<p><\/p>\n<p>* K\u00fcrzlich wurde in ClickHouse im experimentellen Modus die Unterst\u00fctzung f\u00fcr das kompakte Format von St\u00fccke und St\u00fccke im Arbeitsspeicher mit Write-Ahead-Log hinzugef\u00fcgt, was das Problem nahezu vollst\u00e4ndig l\u00f6st.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/b8c6cecdba53559dad31ed11713a980d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Lassen Sie uns nun die zweite Art von Problemen betrachten \u2013 die Typisierung von Daten. <\/p>\n<p><\/p>\n<p>Es gibt strenge und stringbasierte Typisierung. Stringbasiert bedeutet, dass Sie einfach erkl\u00e4rt haben, alle Felder seien vom Typ string. Das ist nicht ideal. So sollte man es nicht machen. <\/p>\n<p><\/p>\n<p>Lassen Sie uns kl\u00e4ren, wie man es richtig macht, wenn man sagen m\u00f6chte, dass ein bestimmtes Feld ein String ist, und ClickHouse die Arbeit erledigen soll, ohne dass ich mir dabei viel M\u00fche machen muss. Es ist jedoch trotzdem wichtig, einige Anstrengungen zu unternehmen. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/a0fdcf6423933293318411242fe2ede7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Nehmen wir beispielsweise eine IP-Adresse. In einem Fall haben wir sie als String gespeichert, etwa 192.168.1.1. In einem anderen Fall wird sie eine Zahl des Typs UInt32* sein. 32 Bit sind ausreichend f\u00fcr eine IPv4-Adresse.<\/p>\n<p><\/p>\n<p>Erstens, auch wenn es seltsam klingt, wird die Datenkomprimierung ungef\u00e4hr gleich sein. Es wird sicher Unterschiede geben, aber nicht so gro\u00dfe. Daher gibt es beim Festplattendurchsatz keine gravierenden Probleme. <\/p>\n<p><\/p>\n<p>Aber es gibt einen erheblichen Unterschied in der CPU-Zeit und der Ausf\u00fchrungszeit der Abfrage. <\/p>\n<p><\/p>\n<p>Berechnen wir die Anzahl der einzigartigen IP-Adressen, wenn sie als Zahlen gespeichert sind. Das ergibt 137 Millionen Zeilen pro Sekunde. Wenn es dasselbe in Form von Strings ist, dann 37 Millionen Zeilen pro Sekunde. Ich wei\u00df nicht, warum es diese \u00dcbereinstimmung gibt. Ich habe diese Abfragen selbst ausgef\u00fchrt. Dennoch ist es etwa viermal langsamer. <\/p>\n<p><\/p>\n<p>Wenn wir den Unterschied im Speicherplatz auf der Festplatte berechnen, gibt es auch einen Unterschied. Und dieser Unterschied betr\u00e4gt etwa ein Viertel, weil es viele einzigartige IP-Adressen gibt. Wenn es hier Zeilen mit einer geringen Anzahl verschiedener Werte g\u00e4be, k\u00f6nnten diese problemlos nach dem W\u00f6rterbuch in etwa gleichem Umfang komprimiert werden. <\/p>\n<p><\/p>\n<p>Und ein vierfacher Zeitunterschied auf der Stra\u00dfe liegt nicht einfach so herum. Vielleicht ist es Ihnen egal, aber wenn ich so einen Unterschied sehe, macht mich das traurig.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/f74dbfdab5a9e26fa044a5870a8cc00d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Lassen Sie uns verschiedene F\u00e4lle betrachten. <\/p>\n<p><\/p>\n<p>1. Ein Fall, wenn Sie nur wenige unterschiedliche eindeutige Werte haben. In diesem Fall verwenden wir eine einfache Praxis, die Sie wahrscheinlich kennen und in allen Datenbanksystemen nutzen k\u00f6nnen. Das gilt nicht nur f\u00fcr ClickHouse. Sie speichern einfach numerische Identifikatoren in der Datenbank. Und die Umwandlung in Strings und zur\u00fcck k\u00f6nnen Sie dann in Ihrer Anwendung vornehmen. <\/p>\n<p><\/p>\n<p>Nehmen wir an, Sie haben eine Region. Und Sie versuchen, sie als String zu speichern. Dort steht dann: Moskau und MO. Und wenn ich sehe, dass dort \u201eMoskau\u201c steht, ist das noch in Ordnung, aber wenn auch MO auftaucht, wird es schon irgendwie traurig. Das sind schlie\u00dflich viele Bytes. <\/p>\n<p><\/p>\n<p>Stattdessen speichern wir einfach die Zahl Ulnt32 und 250. Bei uns sind es 250 in Yandex, bei Ihnen mag es anders sein. Nur f\u00fcr den Fall m\u00f6chte ich darauf hinweisen, dass ClickHouse eine integrierte M\u00f6glichkeit hat, mit geografischen Datenbanken zu arbeiten. Sie speichern einfach ein Verzeichnis mit Regionen, einschlie\u00dflich hierarchischer Strukturen, d. h. dort wird es Moskau, MO und alles, was Sie brauchen, geben. Und Sie k\u00f6nnen auf Abfrageebene konvertieren. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/cc6e871136dab8f8a35246a5af512cda.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Die zweite Option ist im Grunde die gleiche, hat aber bereits Unterst\u00fctzung innerhalb von ClickHouse. Das ist der Datentyp Enum. Sie definieren einfach alle ben\u00f6tigten Werte innerhalb des Enum. Zum Beispiel den Ger\u00e4tetyp, und dort schreiben Sie: Desktop, Mobil, Tablet, Fernseher. Insgesamt 4 Varianten. <\/p>\n<p><\/p>\n<p>Der Nachteil ist, dass man gelegentlich ein Alter durchf\u00fchren muss. Man hat nur eine Variante hinzugef\u00fcgt. Wir f\u00fchren alter table durch. Tats\u00e4chlich ist alter table in ClickHouse kostenlos. Besonders kostenlos f\u00fcr Enum, da sich die Daten auf der Festplatte nicht \u00e4ndern. Dennoch erfordert das Alter eine Sperre f\u00fcr die Tabelle und muss warten, bis alle select-Befehle abgeschlossen sind. Erst danach wird das Alter ausgef\u00fchrt, d. h. einige Unannehmlichkeiten bleiben vorhanden.<\/p>\n<p><\/p>\n<p>* In aktuellen Versionen von ClickHouse ist ALTER vollst\u00e4ndig nicht blockierend.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/d7284fa5be583ab063bb6de0b60f54d4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Eine weitere Option, die f\u00fcr ClickHouse recht einzigartig ist, ist die Anbindung externer Verzeichnisse. Sie k\u00f6nnen Zahlen in ClickHouse speichern und Ihre Verzeichnisse in einem beliebigen f\u00fcr Sie bequemen System halten. Zum Beispiel kann man MySQL, Mongo, Postgres verwenden. Man kann sogar einen eigenen Mikroservice erstellen, der diese Daten \u00fcber HTTP bereitstellt. Und auf der Ebene von ClickHouse schreiben Sie eine Funktion, die diese Daten von Zahlen in Strings umwandelt. <\/p>\n<p><\/p>\n<p>Dies ist eine spezialisierte, aber sehr effektive Methode, um einen Join mit einer externen Tabelle durchzuf\u00fchren. Dabei gibt es zwei Varianten. In der einen Variante werden die Daten vollst\u00e4ndig zwischengespeichert, sind vollst\u00e4ndig im Arbeitsspeicher vorhanden und werden mit einer gewissen Periodizit\u00e4t aktualisiert. In der anderen Variante, wenn diese Daten nicht in den Arbeitsspeicher passen, k\u00f6nnen sie teilweise zwischengespeichert werden. <\/p>\n<p><\/p>\n<p>Hier ein Beispiel. Es gibt Yandex.Direct. Dort gibt es eine Werbekampagne und Banner. Wahrscheinlich gibt es etwa zehn Millionen Werbekampagnen. Diese passen ungef\u00e4hr in den Arbeitsspeicher. Bei den Bannern hingegen \u2013 Milliarden, die passen nicht. Und wir nutzen ein zwischenspeicherbares W\u00f6rterbuch aus MySQL.<\/p>\n<p><\/p>\n<p>Das einzige Problem ist, dass das zwischenspeicherbare W\u00f6rterbuch nur gut funktioniert, wenn die Trefferquote nahe bei 100 % liegt. Wenn sie geringer ist, muss man bei der Verarbeitung von Anfragen f\u00fcr jede Datenmenge tats\u00e4chlich die fehlenden Schl\u00fcssel holen und die Daten aus MySQL abfragen. Bei ClickHouse kann ich mich jedoch darauf verlassen, dass es nicht bremst; \u00fcber andere Systeme m\u00f6chte ich nichts sagen.<\/p>\n<p><\/p>\n<p>Als Bonus ist zu erw\u00e4hnen, dass W\u00f6rterb\u00fccher eine sehr einfache M\u00f6glichkeit sind, Daten in ClickHouse nachtr\u00e4glich zu aktualisieren. D. h., wenn Sie einen Bericht \u00fcber die Werbekampagnen hatten, hat der Benutzer einfach die Werbekampagne ge\u00e4ndert und in allen alten Daten, in allen Berichten, wurden diese Daten ebenfalls ge\u00e4ndert. Wenn man Daten direkt in die Tabelle schreiben w\u00fcrde, w\u00e4re eine Aktualisierung nicht m\u00f6glich. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/a5a2919d6be7d00c0ad5875b9a8f0f31.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Eine weitere Methode, wenn Sie nicht wissen, woher Sie die Identifikatoren f\u00fcr Ihre Zeilen beziehen sollen, ist, sie einfach zu hashen. Der einfachste Weg besteht darin, einen 64-Bit-Hash zu verwenden. <\/p>\n<p><\/p>\n<p>Das einzige Problem ist, dass, wenn der Hash 64 Bit betr\u00e4gt, Kollisionen fast sicher auftreten werden. Denn wenn es viel mehr als eine Milliarde Zeilen gibt, wird die Wahrscheinlichkeit merklich sp\u00fcrbar. <\/p>\n<p><\/p>\n<p>Es w\u00e4re auch nicht ideal, die Namen der Werbekampagnen so zu hashen. Wenn die Werbekampagnen von verschiedenen Unternehmen durcheinander geraten, wird es unverst\u00e4ndlich. <\/p>\n<p><\/p>\n<p>Es gibt einen einfachen Trick. Es stimmt, dass es f\u00fcr ernsthafte Daten nicht sehr geeignet ist, aber wenn es etwas weniger Ernstes ist, f\u00fcgen Sie einfach die Kunden-ID zu dem W\u00f6rterbuchschl\u00fcssel hinzu. Dann werden Sie zwar Kollisionen haben, aber nur innerhalb eines Kunden. So wird es bei uns f\u00fcr die Linkkarten in Yandex.Metrica verwendet. Wir haben dort URLs, wir speichern Hashes. Und wir wissen, dass es nat\u00fcrlich Kollisionen gibt. Aber wenn die Seite angezeigt wird, ist die Wahrscheinlichkeit, dass genau auf einer Seite bei einem Benutzer einige URLs verschwommen wurden und dass dies \u00fcberhaupt bemerkt wird, vernachl\u00e4ssigbar. <\/p>\n<p><\/p>\n<p>Als Bonus \u2013 f\u00fcr viele Operationen reichen einfach die Hashes, und die eigentlichen Strings m\u00fcssen nirgendwo gespeichert werden. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/abbb73aaba29d10e3b7e7650bf68e6a6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ein anderes Beispiel: Wenn die Strings kurz sind, beispielsweise die Domains von Websites. Diese k\u00f6nnen genau so gespeichert werden. Oder zum Beispiel die Sprache des Browsers ru \u2013 2 Byte. Es tut mir nat\u00fcrlich leid um die kleinen Bytes, aber machen Sie sich keine Sorgen, 2 Byte sind nicht viel. Bitte, speichern Sie, wie es ist, machen Sie sich keinen Kopf. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/901eaed0029da6ea59630b57ccf80c25.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ein anderer Fall ist, wenn es umgekehrt sehr viele Strings gibt, und in ihnen sehr viele einzigartige, und zudem eine potenziell unbegrenzte Vielzahl. Ein typisches Beispiel sind Suchanfragen oder URLs. Suchanfragen, auch aufgrund von Tippfehlern. Schauen wir, wie viele einzigartige Suchanfragen an einem Tag vorkommen. Es stellt sich heraus, dass es fast die H\u00e4lfte aller Ereignisse sind. In diesem Fall k\u00f6nnten Sie denken, dass die Daten normalisiert werden m\u00fcssen, IDs gez\u00e4hlt werden und in einer separaten Tabelle gespeichert werden sollten. Aber das muss nicht sein. Speichern Sie diese Strings einfach, wie sie sind. <\/p>\n<p><\/p>\n<p>Besser \u2013 erfinden Sie nichts, denn wenn Sie sie separat speichern, ist ein Join erforderlich. Und dieser Join ist im besten Fall ein zuf\u00e4lliger Zugriff auf den Speicher, falls er \u00fcberhaupt in den Speicher passt. Wenn nicht, gibt es \u00fcberhaupt Probleme. <\/p>\n<p><\/p>\n<p>Wenn die Daten jedoch in Place gespeichert werden, werden sie einfach in der ben\u00f6tigten Reihenfolge aus dem Dateisystem gelesen und alles ist in Ordnung.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/15f1d632083def16ccbc939579c1cf6b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Wenn Sie URLs oder eine andere komplexe lange Zeichenfolge haben, sollten Sie in Betracht ziehen, dass Sie eine Art Zusammenfassung im Voraus berechnen und in einer separaten Spalte speichern k\u00f6nnen. <\/p>\n<p><\/p>\n<p>F\u00fcr URLs k\u00f6nnen Sie beispielsweise die Domain separat speichern. Und wenn Sie tats\u00e4chlich die Domain ben\u00f6tigen, verwenden Sie einfach diese Spalte, w\u00e4hrend die URLs liegen bleiben und Sie sie nicht einmal ber\u00fchren werden. <\/p>\n<p><\/p>\n<p>Lassen Sie uns sehen, welche Unterschiede entstehen. In ClickHouse gibt es eine spezialisierte Funktion, die die Domain berechnet. Sie ist sehr schnell, wir haben sie optimiert. Und um ehrlich zu sein, entspricht sie nicht einmal dem RFC, aber dennoch berechnet sie alles, was wir ben\u00f6tigen. <\/p>\n<p><\/p>\n<p>In einem Fall werden wir einfach die URLs abrufen und die Domain berechnen. Das ergibt 166 Millisekunden. Wenn wir jedoch die fertige Domain nehmen, kommen wir nur auf 67 Millisekunden, das hei\u00dft, fast dreimal schneller. Und zwar schneller nicht, weil wir irgendwelche Berechnungen durchf\u00fchren m\u00fcssen, sondern weil wir weniger Daten lesen. <\/p>\n<p><\/p>\n<p>Warum hat ein langsamerer Abfrage jedoch eine h\u00f6here Geschwindigkeit in Gigabyte pro Sekunde? Weil er mehr Gigabyte liest. Das sind v\u00f6llig \u00fcberfl\u00fcssige Daten. Die Abfrage scheint schneller zu sein, wird aber \u00fcber einen l\u00e4ngeren Zeitraum ausgef\u00fchrt.<\/p>\n<p><\/p>\n<p>Wenn man sich das Volumen der Daten auf der Festplatte ansieht, stellt sich heraus, dass die URL 126 Megabyte und die Domain nur 5 Megabyte betr\u00e4gt. Das macht in der Tat 25-mal weniger. Dennoch wird die Abfrage nur 4-mal schneller ausgef\u00fchrt. Aber das liegt daran, dass die Daten hei\u00df sind. W\u00e4ren sie kalt, w\u00e4re es sicherlich 25-mal schneller aufgrund der Festplatten-E\/A. <\/p>\n<p><\/p>\n<p>Wenn man \u00fcbrigens absch\u00e4tzt, wie viel kleiner die Domain im Vergleich zur URL ist, ergibt sich ein Faktor von etwa 4. Aber warum belegen die Daten auf der Festplatte 25-mal weniger Platz? Wegen der Kompression. Sowohl die URL als auch die Domain werden komprimiert. Oft enth\u00e4lt die URL jedoch eine Menge M\u00fcll. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/c93d2128a41561ed7abb25d77414bc2d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Und nat\u00fcrlich sollte man die richtigen Datentypen verwenden, die speziell f\u00fcr die erforderlichen Werte oder die passenden vorgesehen sind. Wenn Sie IPv4 verwenden, speichern Sie UInt32*. Wenn IPv6, dann FixedString(16), denn eine IPv6-Adresse ist 128 Bit, das hei\u00dft, speichern Sie sie direkt im Bin\u00e4rformat. <\/p>\n<p><\/p>\n<p>Was ist, wenn Sie manchmal IPv4-Adressen und manchmal IPv6-Adressen haben? Ja, man kann beide speichern. Eine Spalte f\u00fcr IPv4, die andere f\u00fcr IPv6. Nat\u00fcrlich gibt es die M\u00f6glichkeit, IPv4 in IPv6 abzubilden. Das wird auch funktionieren, aber wenn Sie in Ihren Abfragen oft genau die IPv4-Adresse ben\u00f6tigen, w\u00e4re es gut, sie in eine separate Spalte zu stecken. <\/p>\n<p><\/p>\n<p>* Jetzt gibt es in ClickHouse spezielle Datentypen f\u00fcr IPv4 und IPv6, die Daten ebenso effizient wie Zahlen speichern, sie jedoch auch so bequem darstellen wie Strings.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/d7d6342ebd6b8b4f3526b3cd8a06cf26.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Es ist auch wichtig zu beachten, dass es sinnvoll ist, die Daten im Voraus vorzubereiten. Zum Beispiel, wenn Ihnen rohe Protokolle vorliegen. Und vielleicht sollten Sie sie nicht sofort in ClickHouse einspeisen, obwohl es verlockend ist, nichts zu tun und alles zu funktionieren. Aber es ist trotzdem besser, die Berechnungen durchzuf\u00fchren, die m\u00f6glich sind.<\/p>\n<p><\/p>\n<p>Zum Beispiel die Version des Browsers. In einer benachbarten Abteilung, auf die ich nicht zeigen m\u00f6chte, wird die Browserversion so gespeichert, d. h. als Zeichenkette: 12.3. Und dann, um einen Bericht zu erstellen, nehmen sie diese Zeichenkette, teilen sie durch ein Array und dann durch das erste Element des Arrays. Nat\u00fcrlich wird alles langsamer. Ich habe gefragt, warum sie das so machen. Sie haben mir geantwortet, dass sie vorzeitige Optimierung nicht m\u00f6gen. Aber ich mag vorzeitige Pessimierung nicht.<\/p>\n<p><\/p>\n<p>In diesem Fall ist es also richtiger, in 4 Spalten zu unterteilen. F\u00fcrchten Sie sich nicht, denn das ist ClickHouse. ClickHouse ist eine spaltenbasierte Datenbank. Je mehr sorgf\u00e4ltig ausgearbeitete kleine Spalten, desto besser. Wenn es 5 BrowserVersionen gibt, machen Sie 5 Spalten. Das ist in Ordnung. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/f9a67221bf8508933d7bd336b16f9e04.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Betrachten wir nun, was zu tun ist, wenn Sie viele sehr lange Zeichenfolgen und sehr lange Arrays haben. Diese m\u00fcssen \u00fcberhaupt nicht in ClickHouse gespeichert werden. Stattdessen k\u00f6nnen Sie in ClickHouse nur eine Art Identifikator speichern. Und diese langen Strings sollten in ein anderes System \u00fcbertragen werden. <\/p>\n<p><\/p>\n<p>Zum Beispiel gibt es in einem unserer Analysetools einige Ereignisparameter. Wenn viele Parameter f\u00fcr Ereignisse ankommen, speichern wir einfach die ersten 512, die wir finden, denn 512 sind nicht zu schade. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/755271e8788ba4bd638f493bf320c820.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Wenn Sie sich nicht \u00fcber Ihre Datentypen entscheiden k\u00f6nnen, k\u00f6nnen Sie auch die Daten in ClickHouse schreiben, aber in eine tempor\u00e4re Tabelle des Typs Log, die speziell f\u00fcr tempor\u00e4re Daten ausgelegt ist. Danach k\u00f6nnen Sie analysieren, wie Ihre Verteilung von Werten aussieht, was es gibt und die richtigen Typen erstellen.<\/p>\n<p><\/p>\n<p>* Derzeit gibt es in ClickHouse den Datentyp <noindex><a rel=\"nofollow\" href=\"https:\/\/clickhouse.tech\/docs\/en\/sql-reference\/data-types\/lowcardinality\/\">LowCardinality<\/a><\/noindex> der es erm\u00f6glicht, Strings effizient mit geringerem Aufwand zu speichern.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/7e9e53d86a4189783c28ce56a669198c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Betrachten wir nun einen weiteren interessanten Fall. Manchmal funktioniert bei den Leuten alles irgendwie merkw\u00fcrdig. Ich gehe hinein und sehe Folgendes. Und sofort kommt die Vorstellung, dass dies von einem sehr erfahrenen, klugen Administrator gemacht wurde, der viel Erfahrung mit der Konfiguration von MySQL Version 3.23 hat. <\/p>\n<p><\/p>\n<p>Hier sehen wir tausend Tabellen, in denen jeweils der Rest der Division von unklar was durch tausend gespeichert ist. <\/p>\n<p><\/p>\n<p>Im Prinzip respektiere ich die Erfahrungen anderer und verstehe auch, durch welche Leiden diese Erfahrungen erworben werden k\u00f6nnen. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/3a5e21ef2076966fcc627670485c5b3a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Die Gr\u00fcnde sind mehr oder weniger klar. Es sind alte Stereotypen, die sich bei der Arbeit mit anderen Systemen angesammelt haben k\u00f6nnten. Zum Beispiel gibt es in MyISAM-Tabellen keinen clusternden Prim\u00e4rschl\u00fcssel. Und diese Art der Datenaufteilung kann ein verzweifelter Versuch sein, die gleiche Funktionalit\u00e4t zu erreichen. <\/p>\n<p><\/p>\n<p>Ein anderer Grund ist, dass es schwierig ist, gro\u00dfe Tabellen mit Operationen wie ALTER zu bearbeiten. Alles wird blockiert. Obwohl dieses Problem in modernen Versionen von MySQL nicht mehr so gravierend ist. <\/p>\n<p><\/p>\n<p>Oder zum Beispiel Mikroscharding, aber dazu mehr sp\u00e4ter.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/321b1d9caa8db7aca5b96e08c61d05b5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>In ClickHouse muss man das nicht tun, denn erstens ist der Prim\u00e4rschl\u00fcssel ein Cluster, und die Daten sind nach dem Prim\u00e4rschl\u00fcssel sortiert. <\/p>\n<p><\/p>\n<p>Manchmal werde ich gefragt: \"Wie ver\u00e4ndert sich die Leistung von Bereichsanfragen in ClickHouse mit der Gr\u00f6\u00dfe der Tabelle?\" Ich sage, dass sie sich gar nicht ver\u00e4ndert. Zum Beispiel haben Sie eine Tabelle mit einer Milliarde Zeilen und lesen einen Bereich von einer Million Zeilen. Alles ist in Ordnung. Wenn die Tabelle eine Billion Zeilen hat und Sie eine Million Zeilen lesen, wird es nahezu dasselbe sein. <\/p>\n<p><\/p>\n<p>Zweitens sind keine manuellen Partitionierungen erforderlich. Wenn Sie schauen, was im Dateisystem dort ist, sehen Sie, dass eine Tabelle eine recht ernsthafte Angelegenheit ist. Und dort gibt es etwas wie Partitionen. Das hei\u00dft, ClickHouse erledigt alles f\u00fcr Sie, und Sie m\u00fcssen nicht leiden.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/652f3742ad3a44f172d0d7302abd09f6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>ALTER in ClickHouse ist kostenlos, wenn es sich um ALTER ADD\/DROP COLUMN handelt. <\/p>\n<p><\/p>\n<p>Und es ist nicht sinnvoll, kleine Tabellen zu erstellen, denn ob Sie 10 Zeilen oder 10.000 Zeilen in Ihrer Tabelle haben, spielt absolut keine Rolle. ClickHouse ist ein System, das den Durchsatz optimiert und nicht die Latenz, sodass es keinen Sinn macht, 10 Zeilen zu verarbeiten. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/144144b4740e9c5daec80c8dadc445f9.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Es ist richtig, eine gro\u00dfe Tabelle zu verwenden. Befreien Sie sich von alten Stereotypen, alles wird gut. <\/p>\n<p><\/p>\n<p>Als Bonus haben wir in der letzten Version die M\u00f6glichkeit eingef\u00fchrt, einen willk\u00fcrlichen Partitionierungsschl\u00fcssel zu erstellen, um Wartungsoperationen an einzelnen Partitionen durchzuf\u00fchren. <\/p>\n<p><\/p>\n<p>Zum Beispiel ben\u00f6tigen Sie viele kleine Tabellen, zum Beispiel, wenn es notwendig ist, einige Zwischendaten zu verarbeiten, die Ihnen in Chunks geliefert werden, und Sie m\u00fcssen Transformationen an ihnen durchf\u00fchren, bevor Sie sie in die endg\u00fcltige Tabelle schreiben. F\u00fcr diesen Fall gibt es einen gro\u00dfartigen Tabellenmotor \u2013 StripeLog. Es ist ungef\u00e4hr wie TinyLog, nur besser. <\/p>\n<p><\/p>\n<p>* Jetzt gibt es in ClickHouse auch <noindex><a rel=\"nofollow\" href=\"https:\/\/clickhouse.tech\/docs\/en\/sql-reference\/table-functions\/input\/\">die tabellarische Funktion input<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/d62f0b3d29876c29c6c0ba236b200186.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ein weiteres Antipattern ist Mikroscharding. Zum Beispiel m\u00fcssen Sie Daten sharden und Sie haben 5 Server, und morgen wird es 6 Server geben. Und Sie denken dar\u00fcber nach, wie Sie diese Daten umverteilen k\u00f6nnen. Stattdessen teilen Sie nicht in 5 Shards auf, sondern in 1.000 Shards. Und dann weisen Sie jeden dieser Mikroschards einem separaten Server zu. Und Sie haben zum Beispiel auf einem Server 200 ClickHouse-Instanzen. Separate Instanzen auf unterschiedlichen Ports oder separate Datenbanken. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/3e550ef7e338b84e4394eb9fa4538769.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Aber in ClickHouse ist das nicht sehr gut. Denn selbst eine Instanz von ClickHouse versucht, alle verf\u00fcgbaren Ressourcen des Servers zu nutzen, um eine Anfrage zu verarbeiten. Das hei\u00dft, Sie haben einen Server und dort zum Beispiel 56 CPU-Kerne. Sie f\u00fchren eine Anfrage aus, die eine Sekunde dauert, und sie wird 56 Kerne nutzen. Wenn Sie dort jedoch 200 ClickHouse-Instanzen auf einem Server platziert haben, werden 10.000 Threads gestartet. Insgesamt wird alles sehr schlecht sein.<\/p>\n<p><\/p>\n<p>Ein weiterer Grund ist, dass die Verteilung der Arbeit auf diese Instanzen ungleichm\u00e4\u00dfig sein wird. Einige werden fr\u00fcher fertig, andere sp\u00e4ter. Wenn das alles in einer Instanz passieren w\u00fcrde, w\u00fcrde ClickHouse selbst herausfinden, wie man die Daten korrekt auf die Threads verteilt. <\/p>\n<p><\/p>\n<p>Und ein weiterer Grund ist, dass es inter-prozessorale Kommunikation \u00fcber TCP geben wird. Die Daten m\u00fcssen serialisiert und deserialisiert werden, und das ist eine enorme Anzahl von Mikroschards. Es wird einfach ineffizient funktionieren.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/18cacc17d22ae1cb2977c6be74769896.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ein weiteres Antipattern, obwohl es schwierig ist, es als solches zu bezeichnen. Das ist eine gro\u00dfe Anzahl an Pre-Aggregationen.<\/p>\n<p><\/p>\n<p>Im Allgemeinen ist Pre-Aggregation gut. Sie hatten eine Milliarde Zeilen, Sie haben sie aggregiert und es sind 1.000 Zeilen geworden, und jetzt wird die Anfrage sofort ausgef\u00fchrt. Alles wunderbar. So kann man das machen. Und daf\u00fcr gibt es sogar in ClickHouse einen speziellen Tabellentyp, den AggregatingMergeTree, der inkrementelle Aggregation w\u00e4hrend des Einf\u00fcgens von Daten durchf\u00fchrt. <\/p>\n<p><\/p>\n<p>Es gibt jedoch F\u00e4lle, in denen Sie denken, dass wir die Daten so aggregieren werden und dann noch so aggregieren. In einer benachbarten Abteilung, von der ich nicht sprechen m\u00f6chte, verwenden sie die SummingMergeTree-Tabellen zur Aggregation nach dem Prim\u00e4rschl\u00fcssel, und als Prim\u00e4rschl\u00fcssel verwenden sie etwa 20 verschiedene Spalten. Ich habe zur Sicherheit einige Spaltennamen zur Tarnung ge\u00e4ndert, aber ungef\u00e4hr so ist es.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/54e3a02ab4bbce7c63ded595780ae1f6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Und es treten solche Probleme auf. Erstens, das Datenvolumen verringert sich nicht drastisch. Zum Beispiel reduziert es sich um das Dreifache. Ein Dreifaches w\u00e4re ein guter Preis, um sich unbegrenzte M\u00f6glichkeiten f\u00fcr Analysen zu erm\u00f6glichen, die entstehen, wenn Ihre Daten nicht aggregiert sind. Wenn die Daten aggregiert sind, erhalten Sie anstelle von Analysen lediglich mickrige Statistiken. <\/p>\n<p><\/p>\n<p>Was besonders nervt? Dass diese Leute aus der benachbarten Abteilung manchmal kommen und darum bitten, noch eine Spalte zum Prim\u00e4rschl\u00fcssel hinzuzuf\u00fcgen. D. h. wir haben die Daten so aggregiert, wollen jetzt aber etwas mehr. Aber in ClickHouse gibt es kein \u00c4ndern des Prim\u00e4rschl\u00fcssels. Deshalb muss man irgendwelche Skripte in C++ schreiben. Und ich mag keine Skripte, selbst wenn sie in C++ sind.<\/p>\n<p><\/p>\n<p>Wenn man sich ansieht, wof\u00fcr ClickHouse entwickelt wurde, sind nicht aggregierte Daten genau das Szenario, f\u00fcr das es geboren wurde. Wenn Sie ClickHouse f\u00fcr nicht aggregierte Daten verwenden, machen Sie alles richtig. Wenn Sie aggregieren, ist das manchmal verzeihlich. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/09fafd4c8a3ea8c22e586cb7a5cf6564.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ein weiterer interessanter Fall sind Abfragen in einer Endlosschleife. Manchmal gehe ich auf einen Produktionsserver und sehe mir die Prozessliste an. Und jedes Mal stelle ich fest, dass etwas Schreckliches passiert. <\/p>\n<p><\/p>\n<p>Zum Beispiel so etwas. Hier wird sofort klar, dass man alles in einer Abfrage h\u00e4tte ausf\u00fchren k\u00f6nnen. Schreiben Sie einfach dort url in und die Liste.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/ae03b659f178962f50e0640614517296.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Warum sind so viele solcher Abfragen in einer Endlosschleife schlecht? Wenn der Index nicht verwendet wird, haben Sie viele Durchl\u00e4ufe \u00fcber dieselben Daten. Aber wenn der Index verwendet wird, zum Beispiel, wenn Sie einen Prim\u00e4rschl\u00fcssel nach ru haben und Sie schreiben url = irgendetwas. Und Sie denken, dass nur dieser eine url genau aus der Tabelle gelesen wird, wird alles in Ordnung sein. Aber in Wirklichkeit ist das nicht der Fall. Denn ClickHouse arbeitet alles in B\u00fcndeln ab. <\/p>\n<p><\/p>\n<p>Wenn er einen bestimmten Datenbereich lesen muss, liest er ein wenig mehr, da der Index in ClickHouse sp\u00e4rlich ist. Dieser Index erm\u00f6glicht es nicht, eine individuelle Zeile in der Tabelle zu finden, sondern nur einen bestimmten Bereich. Die Daten werden in Bl\u00f6cken komprimiert. Um eine Zeile zu lesen, muss man einen ganzen Block nehmen und ihn dekomprimieren. Wenn Sie viele Abfragen durchf\u00fchren, gibt es viele \u00dcberschneidungen, und eine Menge Arbeit wird immer wiederholt.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/95eef43c5b869f8b145c61ce3c616cfd.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Und als Bonus kann man bemerken, dass man in ClickHouse keine Angst haben muss, selbst Megabyte und sogar Hunderte von Megabyte in die IN-Klausel zu \u00fcbergeben. Ich erinnere mich aus unserer Praxis, dass wenn wir in MySQL eine Menge Werte in die IN-Klausel \u00fcbergeben, zum Beispiel 100 Megabyte irgendwelcher Zahlen, dann schluckt MySQL 10 Gigabyte Speicher und sonst passiert nichts, alles funktioniert schlecht. <\/p>\n<p><\/p>\n<p>Und das Zweite ist, dass in ClickHouse, wenn Ihre Abfragen den Index nutzen, es immer nicht langsamer ist als ein Full Scan, d.h. wenn fast die gesamte Tabelle gelesen werden muss, wird es sequenziell durchgef\u00fchrt und die gesamte Tabelle gelesen. Insgesamt k\u00fcmmert sich ClickHouse selbst darum.<\/p>\n<p><\/p>\n<p>Dennoch gibt es einige Schwierigkeiten. Zum Beispiel nutzt die IN-Klausel mit einer Unterabfrage den Index nicht. Aber das ist unser Problem und wir m\u00fcssen das beheben. Es gibt hier nichts Fundamentales. Wir werden es reparieren. <\/p>\n<p><\/p>\n<p>Und eine weitere interessante Sache ist, dass wenn Sie eine sehr lange Abfrage haben und die Verarbeitung der Abfragen verteilt erfolgt, dann wird diese sehr lange Abfrage ohne Kompression an jeden Server gesendet. Zum Beispiel 100 Megabyte und 500 Server. Entsprechend werden \u00fcber das Netzwerk 50 Gigabyte \u00fcbertragen. Es wird \u00fcbertragen und dann wird alles erfolgreich ausgef\u00fchrt.<\/p>\n<p><\/p>\n<p>* benutzt bereits; alles repariert, wie versprochen.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/5fcde9bf04fff0645be2530daa12743f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Und ein recht h\u00e4ufiger Fall ist, wenn Abfragen aus APIs kommen. Zum Beispiel, Sie haben einen eigenen Service erstellt. Und wenn Ihr Service jemandem wichtig ist, dann haben Sie eine API ge\u00f6ffnet und sehen bereits nach zwei Tagen, dass etwas Unverst\u00e4ndliches passiert. Alles ist \u00fcberlastet und es kommen schreckliche Abfragen, die niemals h\u00e4tten kommen sollen. <\/p>\n<p><\/p>\n<p>Und die L\u00f6sung ist einfach. Wenn Sie eine API ge\u00f6ffnet haben, m\u00fcssen Sie sie k\u00fcrzen. Zum Beispiel Quoten einf\u00fchren. Es gibt keine anderen vern\u00fcnftigen Optionen. Andernfalls wird sofort ein Skript geschrieben und es gibt Probleme. <\/p>\n<p><\/p>\n<p>Und ClickHouse bietet eine spezielle M\u00f6glichkeit \u2013 die Z\u00e4hlung von Quoten. Dabei kann man seinen eigenen Quoten-Schl\u00fcssel \u00fcbergeben. Das kann zum Beispiel eine interne Benutzer-ID sein. Und die Quoten werden unabh\u00e4ngig f\u00fcr jeden von ihnen gez\u00e4hlt. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/532438d0f116919e62f04e32ebbd3c45.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Jetzt noch eine interessante Sache. Das ist die Replikation mit manueller Steuerung. <\/p>\n<p><\/p>\n<p>Ich kenne viele F\u00e4lle, in denen, trotz der integrierten Unterst\u00fctzung f\u00fcr Replikation in ClickHouse, die Leute ClickHouse manuell replizieren.<\/p>\n<p><\/p>\n<p>Welches Prinzip steckt dahinter? Sie haben eine Datenverarbeitungs-Pipeline. Und diese funktioniert unabh\u00e4ngig, zum Beispiel in verschiedenen Rechenzentren. Sie schreiben die gleichen Daten auf die gleiche Art in ClickHouse. Allerdings zeigt die Praxis, dass die Daten aufgrund bestimmter Besonderheiten in Ihrem Code dennoch auseinanderdriften werden. Ich hoffe, in Ihrem nicht. <\/p>\n<p><\/p>\n<p>Und gelegentlich m\u00fcssen Sie trotzdem manuell synchronisieren. Zum Beispiel f\u00fchren die Administratoren einmal im Monat ein rsync durch.<\/p>\n<p><\/p>\n<p>In der Tat ist es viel einfacher, die in ClickHouse integrierte Replikation zu verwenden. Aber es kann einige Vorbehalte geben, denn daf\u00fcr m\u00fcssen Sie ZooKeeper verwenden. Ich will nichts Schlechtes \u00fcber ZooKeeper sagen, grunds\u00e4tzlich ist das System funktional, aber es kommt vor, dass Menschen es aufgrund von Java-Phobie nicht verwenden, denn ClickHouse ist ein gutes System, das in C++ geschrieben ist, das man nutzen kann und das hervorragend funktioniert. Aber ZooKeeper ist in Java. Und man hat irgendwie nicht das Bed\u00fcrfnis, sich das anzusehen, aber dann k\u00f6nnen Sie die Replikation mit manueller Steuerung verwenden. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/3b5b68996daef6b8920f067b189f25e0.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>ClickHouse ist ein praktisches System. Es ber\u00fccksichtigt Ihre Bed\u00fcrfnisse. Wenn Sie Replikation mit manueller Steuerung haben, k\u00f6nnen Sie eine verteilte Tabelle erstellen, die auf Ihre manuellen Replikate schaut und selbst zwischen diesen einen Failover durchf\u00fchrt. Es gibt sogar eine spezielle Option, die es erm\u00f6glicht, Flaps zu vermeiden, selbst wenn Ihre Replikate systematisch auseinandergehen.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/70f6630f8b14756163923a7db8dd7391.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Es k\u00f6nnen Probleme auftreten, wenn Sie primitive Table Engines verwenden. ClickHouse ist eine Art Baukasten mit einer Vielzahl verschiedener Tabellen-Engines. F\u00fcr alle ernsten F\u00e4lle sollte, wie in der Dokumentation angegeben, die MergeTree-Familie verwendet werden. Alle anderen sind eher f\u00fcr spezielle F\u00e4lle oder Tests gedacht.<\/p>\n<p><\/p>\n<p>In der MergeTree-Tabelle ist es nicht unbedingt erforderlich, dass Sie ein Datum und eine Uhrzeit haben. Sie k\u00f6nnen sie dennoch verwenden. Wenn es kein Datum und keine Uhrzeit gibt, geben Sie an, dass das Standarddatum das Jahr 2000 ist. Das wird funktionieren und ben\u00f6tigt keine Ressourcen. <\/p>\n<p><\/p>\n<p>In der neuen Serverversion k\u00f6nnen Sie sogar angeben, dass Sie eine benutzerdefinierte Partitionierung ohne Partitionsschl\u00fcssel haben m\u00f6chten. Es bleibt dasselbe. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/6d4046d11afdd1e5962d49a1612b666a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Andererseits k\u00f6nnen primitive Tabellensysteme verwendet werden. Zum Beispiel k\u00f6nnen Sie Daten einmal importieren und dann spielen, drehen und l\u00f6schen. Sie k\u00f6nnen Log verwenden.<\/p>\n<p><\/p>\n<p>Oder die Speicherung kleiner Datenmengen zur Zwischenverarbeitung \u2013 das ist StripeLog oder TinyLog.<\/p>\n<p><\/p>\n<p>Memory kann verwendet werden, wenn Sie eine kleine Datenmenge haben und einfach etwas im RAM bewegen m\u00f6chten. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/8a3d4e0e3a8c26dd3a2b2f64123e2bf9.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>ClickHouse mag keine \u00fcber-normalisierten Daten. <\/p>\n<p><\/p>\n<p>Hier ist ein typisches Beispiel. Es gibt eine riesige Menge an URLs. Sie haben sie in eine benachbarte Tabelle gesteckt. Und dann wollten Sie damit JOIN machen, aber das funktioniert normalerweise nicht, da ClickHouse nur Hash JOIN unterst\u00fctzt. Wenn nicht gen\u00fcgend RAM f\u00fcr die vielen Daten vorhanden ist, die verbunden werden m\u00fcssen, kann der JOIN nicht ausgef\u00fchrt werden*. <\/p>\n<p><\/p>\n<p>Wenn die Daten eine hohe Kardinalit\u00e4t haben, machen Sie sich keine Sorgen, halten Sie sie in denormalisierter Form, URLs direkt inplace in der Haupttabelle. <\/p>\n<p><\/p>\n<p>* Aber jetzt gibt es in ClickHouse auch Merge JOIN, und er funktioniert unter Bedingungen, wenn die Zwischendaten nicht im RAM Platz finden. Aber das ist ineffizient, und die Empfehlung bleibt bestehen.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/e8160a8db17c18d48f810092c55b094c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Hier sind noch ein paar Beispiele, aber ich zweifle bereits, ob sie antipattern sind oder nicht. <\/p>\n<p><\/p>\n<p>In ClickHouse gibt es einen bekannten Nachteil. Er kann keine Updates durchf\u00fchren*. In gewissem Sinne ist das sogar gut. Wenn Sie wichtige Daten haben, zum Beispiel Buchhaltungsdaten, kann niemand sie senden, weil es keine Updates gibt.<\/p>\n<p><\/p>\n<p>* Unterst\u00fctzung f\u00fcr Updates und Deletes im Batch-Modus wurde schon lange hinzugef\u00fcgt.<\/p>\n<p><\/p>\n<p>Aber es gibt einige spezielle Methoden, die es erm\u00f6glichen, Updates gewisserma\u00dfen im Hintergrund durchzuf\u00fchren. Zum Beispiel Tabellen vom Typ ReplaceMergeTree. Sie f\u00fchren Updates w\u00e4hrend der Hintergrund-Merges durch. Sie k\u00f6nnen dies mit optimize table erzwingen. Aber machen Sie das nicht zu oft, denn das f\u00fchrt zur vollst\u00e4ndigen Neuschreibung der Partition. <\/p>\n<p><\/p>\n<p>Verteilte JOINs in ClickHouse werden vom Query-Planer ebenfalls schlecht verarbeitet. <\/p>\n<p><\/p>\n<p>Schlecht, aber manchmal in Ordnung.<\/p>\n<p><\/p>\n<p>Die Verwendung von ClickHouse nur, um Daten \u00fcber select* zur\u00fcckzulesen.<\/p>\n<p><\/p>\n<p>Ich w\u00fcrde nicht empfehlen, ClickHouse f\u00fcr umfangreiche Berechnungen zu verwenden. Aber so ganz stimmt das nicht, denn wir gehen bereits von dieser Empfehlung ab. Und k\u00fcrzlich haben wir die M\u00f6glichkeit hinzugef\u00fcgt, Machine-Learning-Modelle in ClickHouse anzuwenden \u2013 Catboost. Das bereitet mir Sorgen, denn ich denke: \"Wie schrecklich. Wie viele Taktzyklen pro Byte sind das!\" Es tut mir leid, Taktrate f\u00fcr Bytes zu verschwenden. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Effektiver Einsatz von ClickHouse. Alexey Milovidov (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/f686d5d352ccb444cd06e2ae68897137.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Aber keine Angst, installieren Sie ClickHouse, alles wird gut. Wenn Sie Fragen haben, haben wir eine Community. \u00dcbrigens, die Community sind Sie. Und wenn Sie irgendwelche Probleme haben, k\u00f6nnen Sie zumindest in unseren Chat kommen, und ich hoffe, dass Ihnen geholfen wird. <\/p>\n<p><\/p>\n<p>Fragen<\/p>\n<p><\/p>\n<p><em>Danke f\u00fcr die Pr\u00e4sentation! Wo kann ich mich \u00fcber einen ClickHouse-Absturz beschweren?<\/em><\/p>\n<p><\/p>\n<p>Sie k\u00f6nnen sich gerne direkt jetzt an mich wenden. <\/p>\n<p><\/p>\n<p><em>Ich habe k\u00fcrzlich angefangen, ClickHouse zu verwenden. Ich habe sofort die CLI-Oberfl\u00e4che zum Absturz gebracht.<\/em><\/p>\n<p><\/p>\n<p>Sie haben Gl\u00fcck. <\/p>\n<p><\/p>\n<p><em>Kurze Zeit sp\u00e4ter habe ich den Server mit einer kleinen SELECT-Anfrage zum Absturz gebracht.<\/em><\/p>\n<p><\/p>\n<p>Sie haben Talent. <\/p>\n<p><\/p>\n<p><em>Ich habe einen Bug auf GitHub gemeldet, aber er wurde ignoriert.<\/em> <\/p>\n<p><\/p>\n<p>Schauen wir mal. <\/p>\n<p><\/p>\n<p><em>Alexey hat mich mit einem Trick dazu gebracht, einen Vortrag zu halten, indem er versprochen hat zu erkl\u00e4ren, wie ihr die Daten intern komprimiert.<\/em><\/p>\n<p><\/p>\n<p>Ganz einfach. <\/p>\n<p><\/p>\n<p><em>Das habe ich auch schon gestern verstanden. Mehr Konkretes.<\/em> <\/p>\n<p><\/p>\n<p>Es gibt keine fiesen Tricks. Es handelt sich einfach um Blockkompression. Standardm\u00e4\u00dfig wird LZ4 verwendet, Sie k\u00f6nnen ZSTD aktivieren*. Die Bl\u00f6cke sind von 64 Kilobyte bis 1 Megabyte.<\/p>\n<p><\/p>\n<p>* Es gibt auch Unterst\u00fctzung f\u00fcr spezialisierte Kompressionscodecs, die in Kombination mit anderen Algorithmen verwendet werden k\u00f6nnen.<\/p>\n<p><\/p>\n<p><em>Sind die Daten in den Bl\u00f6cken einfach rohe Daten?<\/em><\/p>\n<p><\/p>\n<p>Nicht ganz roh. Dort sind Arrays. Wenn Sie eine numerische Spalte haben, sind die Zahlen in einem Array hintereinander angeordnet. <\/p>\n<p><\/p>\n<p><em>Verstanden.<\/em> <\/p>\n<p><\/p>\n<p><em>Alexey, das Beispiel mit uniqExact \u00fcber die IP-Adressen, d. h. dass uniqExact \u00fcber Strings l\u00e4nger braucht als \u00fcber Zahlen usw. Und was ist, wenn wir einen Trick anwenden und beim Auslesen casten? Das hei\u00dft, Sie haben anscheinend gesagt, dass es auf der Festplatte nicht so viel Unterschied gibt. Wenn wir Strings von der Festplatte lesen und casten, sind die Aggregationen dann schneller oder nicht? Oder gewinnen wir hier dennoch nur geringf\u00fcgig? Mir scheint, dass Sie das getestet haben, aber aus irgendeinem Grund nicht im Benchmark angegeben haben.<\/em> <\/p>\n<p><\/p>\n<p>Ich denke, dass es langsamer sein wird als ohne Casting. In diesem Fall muss die IP-Adresse aus der Zeichenkette geparsed werden. Nat\u00fcrlich ist in ClickHouse auch das Parsen von IP-Adressen optimiert. Wir haben uns sehr angestrengt, aber die Zahlen sind in Zehntausenderform geschrieben. Sehr unpraktisch. Auf der anderen Seite wird die Funktion uniqExact bei Zeichenfolgen langsamer arbeiten, nicht nur weil es Zeichenfolgen sind, sondern auch weil eine andere Algorithmusspezialisierung gew\u00e4hlt wird. Zeichenfolgen werden einfach anders verarbeitet.<\/p>\n<p><\/p>\n<p><em>Und wenn wir einen primitiveren Datentyp nehmen? Zum Beispiel haben wir die Benutzer-ID, die wir im Input haben, als Zeichenkette gespeichert und dann gecastet. Wird es dann besser oder schlechter?<\/em><\/p>\n<p><\/p>\n<p>Ich habe Zweifel. Ich denke sogar, dass es trauriger sein wird, denn das Parsen von Zahlen ist schlie\u00dflich ein ernsthaftes Problem. Mir scheint, dass ein Kollege sogar einen Vortrag \u00fcber die Schwierigkeiten beim Parsen von Zahlen in Zehntausenderform gehalten hat, oder vielleicht auch nicht. <\/p>\n<p><\/p>\n<p><em>Alexey, vielen Dank f\u00fcr den Vortrag! Und danke auch f\u00fcr ClickHouse! Ich habe eine Frage zu den Pl\u00e4nen. Gibt es Pl\u00e4ne f\u00fcr eine Funktion, um W\u00f6rterb\u00fccher nicht vollst\u00e4ndig zu aktualisieren?<\/em><\/p>\n<p><\/p>\n<p>Das hei\u00dft, partielle Neulandung?<\/p>\n<p><\/p>\n<p><em>Ja, genau. So eine M\u00f6glichkeit, ein MySQL-Feld anzugeben, d. h. nachtr\u00e4glich zu aktualisieren, sodass nur diese Daten geladen werden, wenn das W\u00f6rterbuch sehr gro\u00df ist.<\/em><\/p>\n<p><\/p>\n<p>Eine sehr interessante Funktion. Und ich glaube, jemand hat dies in unserem Chat vorgeschlagen. Vielleicht waren Sie das sogar. <\/p>\n<p><\/p>\n<p><em>Ich glaube nicht, dass ich das war.<\/em><\/p>\n<p><\/p>\n<p>Gro\u00dfartig, jetzt ergibt sich, dass es zwei Anfragen gibt. Und wir k\u00f6nnen in Ruhe anfangen, daran zu arbeiten. Aber ich m\u00f6chte Sie sofort warnen, dass diese Funktion ziemlich einfach umzusetzen ist. Das hei\u00dft, theoretisch muss man einfach die Versionsnummer in die Tabelle schreiben und dann schreiben: Version kleiner als diese. Das bedeutet, dass wir wahrscheinlich vorschlagen werden, dies Enthusiasten zu \u00fcberlassen. Sind Sie ein Enthusiast? <\/p>\n<p><\/p>\n<p><em>Ja, aber leider nicht in C++.<\/em><\/p>\n<p><\/p>\n<p>K\u00f6nnen Ihre Kollegen in C++ programmieren? <\/p>\n<p><\/p>\n<p><em>Ich werde jemanden finden.<\/em><\/p>\n<p><\/p>\n<p>Ausgezeichnet*.<\/p>\n<p><\/p>\n<p>* Die M\u00f6glichkeit wurde zwei Monate nach dem Vortrag hinzugef\u00fcgt \u2013 sie wurde vom Autor der Frage entwickelt und gesendet. <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/ClickHouse\/ClickHouse\/pull\/1771\">Pull-Request<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p><em>Danke!<\/em><\/p>\n<p><\/p>\n<p><em>Hallo! Vielen Dank f\u00fcr den Vortrag! Sie haben erw\u00e4hnt, dass ClickHouse alle verf\u00fcgbaren Ressourcen sehr gut nutzt. Der Referent, der neben Luxoft sprach, berichtete von seiner L\u00f6sung f\u00fcr die Post Russland. Er sagte, dass ihnen ClickHouse sehr gefallen hat, aber sie es nicht anstelle ihres Hauptkonkurrenten verwendet haben, gerade weil es die gesamte CPU-Auslastung beansprucht hat. Und sie konnten es nicht in ihre Architektur, in ihren ZooKeeper mit Docker-Containern integrieren. Gibt es eine M\u00f6glichkeit, ClickHouse irgendwie zu begrenzen, damit es nicht alles verbraucht, was ihm zur Verf\u00fcgung steht?<\/em><\/p>\n<p><\/p>\n<p>Ja, das ist m\u00f6glich und sehr einfach. Wenn Sie m\u00f6chten, dass weniger Kerne verwendet werden, schreiben Sie einfach <code>set max_threads = 1<\/code>. Und das war's, er wird die Anfrage auf einem Kern ausf\u00fchren. Au\u00dferdem k\u00f6nnen verschiedene Benutzer unterschiedliche Einstellungen festlegen. Es gibt also keine Probleme. Und sagen Sie den Kollegen von Luxoft, dass es nicht gut ist, dass sie diese Einstellung in der Dokumentation nicht gefunden haben. <\/p>\n<p><\/p>\n<p><em>Alexei, hallo! Ich w\u00fcrde gerne eine Frage stellen. Ich habe schon mehrmals geh\u00f6rt, dass viele ClickHouse als Log-Speicher verwenden. In Ihrem Vortrag haben Sie gesagt, dass man das nicht tun sollte, d. h. dass man keine langen Zeilen speichern sollte. Was halten Sie davon?<\/em><\/p>\n<p><\/p>\n<p>Erstens sind Logs in der Regel keine langen Zeilen. Es gibt nat\u00fcrlich Ausnahmen. Zum Beispiel, wenn ein Dienst, der in Java geschrieben ist, eine Ausnahme ausl\u00f6st, wird sie protokolliert. Und das in einer endlosen Schleife, bis der Speicherplatz auf der Festplatte ersch\u00f6pft ist. Die L\u00f6sung ist sehr einfach. Wenn die Zeilen sehr lang sind, schneiden Sie sie ab. Und was bedeutet lang? Dutzende Kilobyte sind schlecht*.<\/p>\n<p><\/p>\n<p>* In den aktuellen Versionen von ClickHouse ist die \"adaptive Granularit\u00e4t des Index\" aktiviert, was das Problem der Speicherung von langen Zeichenfolgen weitgehend l\u00f6st.<\/p>\n<p><\/p>\n<p><em>Ist ein Kilobyte normal?<\/em><\/p>\n<p><\/p>\n<p>Normal. <\/p>\n<p><\/p>\n<p><em>Hallo! Vielen Dank f\u00fcr den Vortrag! Ich habe bereits in der Chat gefragt, wei\u00df aber nicht, ob ich eine Antwort erhalten habe. Ist geplant, den WITH-Abschnitt \u00e4hnlich wie CTE zu erweitern?<\/em><\/p>\n<p><\/p>\n<p>Im Moment nicht. Der WITH-Abschnitt ist bei uns etwas unseri\u00f6s. Er ist f\u00fcr uns nur ein kleines Feature.<\/p>\n<p><\/p>\n<p><em>Ich verstehe. Vielen Dank!<\/em><\/p>\n<p><\/p>\n<p><em>Vielen Dank f\u00fcr den Vortrag! Sehr interessant! Eine allgemeine Frage. Ist geplant, vielleicht eine Art Schnittstelle f\u00fcr die Datenl\u00f6schung zu schaffen?<\/em><\/p>\n<p><\/p>\n<p>Unbedingt. Das ist unsere erste Aufgabe in unserer Warteschlange. Wir haben jetzt aktiv dar\u00fcber nachgedacht, wie wir alles richtig machen k\u00f6nnen. Und es ist an der Zeit, mit dem Tippen zu beginnen*.<\/p>\n<p><\/p>\n<p>* Haben die Tasten auf der Tastatur gedr\u00fcckt und alles erledigt.<\/p>\n<p><\/p>\n<p><em>Wird sich das irgendwie auf die Systemleistung auswirken oder nicht? Wird das Einf\u00fcgen genauso schnell sein wie jetzt?<\/em><\/p>\n<p><\/p>\n<p>Vielleicht werden die deletes, die updates sehr schwer sein, aber das wird die Leistung der selects und der inserts nicht beeintr\u00e4chtigen.<\/p>\n<p><\/p>\n<p><em>Und noch eine kleine Frage. Bei der Pr\u00e4sentation sprachen Sie \u00fcber den Prim\u00e4rschl\u00fcssel. Haben wir also eine Partitionierung, die standardm\u00e4\u00dfig monatlich ist, richtig? Und wenn wir einen Datumsbereich festlegen, der in einen Monat f\u00e4llt, wird nur diese Partition gelesen, korrekt?<\/em><\/p>\n<p><\/p>\n<p>Ja.<\/p>\n<p><\/p>\n<p><em>Eine solche Frage. Wenn wir keinen Prim\u00e4rschl\u00fcssel festlegen k\u00f6nnen, ist es dann richtig, ihn nach dem Feld \"Datum\" zu erstellen, um im Hintergrund eine geringere Umstrukturierung dieser Daten zu gew\u00e4hrleisten, damit sie geordneter sind? Wenn Sie keine Bereichsanfragen haben und keinen Prim\u00e4rschl\u00fcssel w\u00e4hlen k\u00f6nnen, sollten Sie dann das Datum in den Prim\u00e4rschl\u00fcssel aufnehmen?<\/em><\/p>\n<p><\/p>\n<p>Ja.<\/p>\n<p><\/p>\n<p>Vielleicht macht es Sinn, ein Feld im Prim\u00e4rschl\u00fcssel aufzunehmen, bei dem die Daten besser komprimiert werden, wenn sie nach diesem Feld sortiert sind. Zum Beispiel die Benutzer-ID. Ein Benutzer besucht beispielsweise immer dieselbe Website. In diesem Fall legen Sie die Benutzer-ID und die Uhrzeit ab. Dann werden Ihre Daten besser komprimiert. Was das Datum betrifft, wenn Sie wirklich keine und niemals Bereichsanfragen nach Datumsangaben haben, dann m\u00fcssen Sie das Datum nicht im Prim\u00e4rschl\u00fcssel ablegen. <\/p>\n<p><\/p>\n<p><em>Gut, vielen Dank!<\/em><\/p>\n<p>Quelle: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/514840\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0422\u0430\u043a \u043a\u0430\u043a ClickHouse \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439, \u043f\u0440\u0438 \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0432\u0430\u0436\u043d\u043e \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u0435\u0433\u043e \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b. \u0412 \u044d\u0442\u043e\u043c \u0434\u043e\u043a\u043b\u0430\u0434\u0435 \u0410\u043b\u0435\u043a\u0441\u0435\u0439 \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0435\u0442 \u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445 \u0442\u0438\u043f\u0438\u0447\u043d\u044b\u0445 \u043e\u0448\u0438\u0431\u043e\u043a \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 ClickHouse, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043a \u043d\u0435\u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u0435. \u041d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445 \u0438\u0437 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0438 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043e, \u043a\u0430\u043a \u0432\u044b\u0431\u043e\u0440 \u0442\u043e\u0439 \u0438\u043b\u0438 \u0438\u043d\u043e\u0439 \u0441\u0445\u0435\u043c\u044b \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u043e\u0436\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043d\u0430 \u043f\u043e\u0440\u044f\u0434\u043a\u0438. \u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442! \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":91439,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-91438","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/effektivnoe-ispolzovanie-clickhouse-aleksej-milovidov-yandeks\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"de_DE\" \/>\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\/de\/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\udd47Effektive Nutzung von ClickHouse. Alexey Milovidov (Yandex) | ProHoster","description":"","canonical_url":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/effektivnoe-ispolzovanie-clickhouse-aleksej-milovidov-yandeks","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"de_DE","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\/de\/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\/de\/wp-json\/wp\/v2\/posts\/91438","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/comments?post=91438"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/91438\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media\/91439"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media?parent=91438"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/categories?post=91438"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/tags?post=91438"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}