Was ist, wenn Ihre Datenbankabfrage nicht schnell genug ausgeführt wird? Woher wissen Sie, ob eine Abfrage Rechenressourcen optimal nutzt oder beschleunigt werden kann? Bei der letzten HighLoad ++ - Konferenz in Moskau habe ich über die Selbstbeobachtung der Abfrageleistung gesprochen - sowohl über die Funktionen des ClickHouse-DBMS als auch über die Betriebssystemfunktionen, die jeder kennen sollte.

Jedes Mal, wenn ich eine Anfrage stelle, geht es mir nicht nur um das Ergebnis, sondern auch darum, was diese Anfrage bewirkt. Zum Beispiel funktioniert es für eine Sekunde. Ist es viel oder wenig? Ich denke immer: warum nicht eine halbe Sekunde? Dann optimiere ich etwas, beschleunige es und es funktioniert für 10 ms. Ich bin normalerweise zufrieden. Trotzdem versuche ich in diesem Fall einen unzufriedenen Gesichtsausdruck zu machen und frage: "Warum nicht 5 ms?" Wie kann ich herausfinden, wie viel Zeit für die Bearbeitung der Anfrage aufgewendet wird? Kann es prinzipiell beschleunigt werden?
In der Regel ist die Verarbeitungsgeschwindigkeit von Anforderungen eine einfache Arithmetik. Wir haben den Code geschrieben - wahrscheinlich optimal - und wir haben ein Gerät im System. Geräte haben Spezifikationen. Zum Beispiel die Lesegeschwindigkeit aus dem L1-Cache. Oder die Anzahl der zufälligen Lesevorgänge, die eine SSD ausführen kann. Das wissen wir alle. Wir müssen diese Eigenschaften nehmen, addieren, subtrahieren, multiplizieren, dividieren und die Antwort überprüfen. Dies ist jedoch im Idealfall so gut wie nie der Fall. Fast. Tatsächlich passiert dies manchmal in ClickHouse.
Berücksichtigen Sie die trivialen Fakten darüber, welche Geräte und welche Ressourcen sich auf unseren Servern befinden.

Prozessor, Speicher, Festplatte, Netzwerk. Ich habe diese Ressourcen speziell so angeordnet, angefangen bei den einfachsten und bequemsten für die Überprüfung und Optimierung bis hin zu den unpraktischsten und komplexesten. Zum Beispiel führe ich eine Anfrage aus und sehe, dass mein Programm auf der CPU zu ruhen scheint. Was bedeutet das? Was ich dort finden werde, ist eine Art innere Schleife, eine Funktion, die am häufigsten ausgeführt wird, den Code neu schreibt, neu kompiliert und einmal - mein Programm läuft schneller.
Wenn Sie zu viel RAM ausgeben, ist alles etwas komplizierter. Sie müssen die Datenstruktur überdenken und einige Bits drücken. In jedem Fall starte ich mein Programm neu und es verbraucht weniger RAM. Dies geht zwar häufig zu Lasten des Prozessors.
Wenn alles von Festplatten abhängt, ist dies auch schwieriger, da ich die Datenstruktur auf der Festplatte ändern kann, diese Daten jedoch später konvertieren muss. Wenn ich eine neue Version erstelle, müssen die Benutzer eine Art Datenmigration durchführen. Es stellt sich heraus, dass die Festplatte bereits viel komplizierter ist, und es ist besser, im Voraus darüber nachzudenken.
Und das Netzwerk ... Ich mag das Netzwerk wirklich nicht, weil es oft völlig unklar ist, was darin passiert, insbesondere wenn es sich um ein Netzwerk zwischen Kontinenten und Rechenzentren handelt. Dort verlangsamt sich etwas, und es ist nicht einmal Ihr Netzwerk, nicht Ihr Server, und Sie können nichts tun. Das einzige, was Sie im Voraus überlegen können, ist, wie die Daten übertragen werden und wie die Interaktion über das Netzwerk minimiert werden kann.
Es kommt vor, dass keine einzige Ressource im System verwendet wird und das Programm nur auf etwas wartet. Tatsächlich ist dies ein sehr häufiger Fall, da unser System verteilt ist und es viele verschiedene Prozesse und Abläufe geben kann und einer auf einen anderen wartet und all dies irgendwie miteinander verbunden sein muss, um dies richtig zu berücksichtigen.

Am einfachsten ist es, die Ressourcennutzung mit einem numerischen Wert zu betrachten. Zum Beispiel starten Sie einige Top, und er schreibt: Der Prozessor ist 100%. Oder führen Sie iostat aus und er schreibt: Festplatten sind 100%. Das reicht oft nicht aus. Eine Person wird sehen, dass das Programm auf Festplatten ruht. Was kann getan werden? Sie können dies einfach notieren und sich ausruhen, entscheiden, dass alles, nichts optimiert werden kann. Tatsächlich ist jedoch jedes der Geräte in sich selbst ziemlich kompliziert. Der Prozessor verfügt über eine Reihe von Computergeräten für verschiedene Arten von Vorgängen. Festplatten haben möglicherweise ein RAID-Array. Wenn es eine SSD gibt, dann gibt es in ihrem eigenen Prozessor einen eigenen Controller, was unklar macht, was. Und ein Wert - 50% oder 100% - reicht nicht aus. Die Grundregel: Wenn Sie feststellen, dass eine Ressource zu 100% ausgelastet ist, geben Sie nicht auf. Oft kann man noch etwas verbessern. Aber es passiert und umgekehrt. Angenommen, Sie sehen, dass das Recycling 50% beträgt, aber nichts getan werden kann.
Schauen wir uns das genauer an.

Die einfachste und bequemste Ressource ist der Prozessor. Sie sehen oben, es heißt, dass der Prozessor 100% ist. Es sollte jedoch beachtet werden, dass dies kein 100% iger Prozessor ist. Das Top-Programm weiß nicht, was der Prozessor dort macht. Sie schaut aus der Perspektive des OS-Planers. Das heißt, jetzt läuft eine Art Programm-Thread auf dem Prozessor. Der Prozessor macht etwas, und dann werden 100% angezeigt, wenn es über die Zeit gemittelt wird. Gleichzeitig macht der Prozessor etwas und es ist nicht klar, wie effektiv es ist. Es kann eine andere Anzahl von Anweisungen pro Zyklus ausführen. Wenn nur wenige Anweisungen vorhanden sind, kann der Prozessor selbst auf etwas warten, z. B. das Laden von Daten aus dem Speicher. Gleichzeitig wird dasselbe oben angezeigt - 100%. Wir warten darauf, dass der Prozessor unseren Anweisungen folgt. Und was er drinnen macht, ist unklar.
Schließlich gibt es nur einen Rechen, wenn Sie denken, dass Ihr Programm auf dem Prozessor ruht. Dies ist wahr, aber aus irgendeinem Grund hat der Prozessor eine niedrigere Frequenz. Es kann viele Gründe geben: Überhitzung, Leistungsbegrenzung. Aus irgendeinem Grund gibt es im Rechenzentrum eine Leistungsbegrenzung, oder die Energieeinsparung kann einfach aktiviert werden. Dann wechselt der Prozessor ständig von einer höheren zu einer niedrigeren Frequenz. Wenn Ihre Last jedoch instabil ist, reicht dies nicht aus und der Code wird im Durchschnitt langsamer ausgeführt. Die aktuelle Prozessorfrequenz finden Sie im Turbostat. In dmesg auf Überhitzung prüfen. Wenn so etwas passieren würde, würde es sagen: „Überhitzung. Frequenz runter. "
Wenn Sie daran interessiert sind, wie viele Cache-Fehler sich darin befanden, wie viele Anweisungen pro Zyklus ausgeführt werden, verwenden Sie perf record. Nehmen Sie ein Beispiel des Programms auf. Weiterhin wird es möglich sein, es mit perf stat oder perf report zu betrachten.

Umgekehrt. Nehmen wir an, Sie schauen nach oben und der Prozessor ist zu weniger als 50% recycelt. Angenommen, Ihr System verfügt über 32 virtuelle Prozessorkerne und 16 physische Kerne. Auf Intel-Prozessoren liegt dies daran, dass das Hyper-Threading doppelt so hoch ist. Dies bedeutet jedoch nicht, dass zusätzliche Kerne unbrauchbar sind. Es hängt alles von der Last ab. Angenommen, Sie haben einige gut optimierte lineare Algebraoperationen oder Sie haben Hashes für das Mining von Bitcoins. Dann ist der Code klar, viele Anweisungen werden pro Zyklus ausgeführt, es gibt keine Cache-Fehler und auch keine Verzweigungsfehler. Und Hyper-Threading hilft nicht. Es ist hilfreich, wenn ein Kern auf etwas wartet, während der andere gleichzeitig Anweisungen von einem anderen Thread ausführen kann.
ClickHouse hat beide Situationen. Wenn wir beispielsweise Datenaggregation (GROUP BY) oder Filterung nach Set (IN-Unterabfrage) durchführen, haben wir eine Hash-Tabelle. Wenn die Hash-Tabelle nicht in den Prozessor-Cache passt, treten Cache-Fehler auf. Dies kann kaum vermieden werden. In diesem Fall hilft uns Hyper-Threading.
Standardmäßig verwendet ClickHouse nur physische Prozessorkerne, ausgenommen Hyper-Threading. Wenn Sie wissen, dass Ihre Anfrage von Hyper-Threading profitieren kann, verdoppeln Sie einfach die Anzahl der Threads: SET max threads = 32, und Ihre Anfrage wird schneller.
Es kommt vor, dass der Prozessor perfekt genutzt wird, aber Sie sehen sich die Grafik an und sehen beispielsweise 10%. Und Ihr Zeitplan beträgt zum Beispiel im schlimmsten Fall fünf Minuten. Selbst wenn es eine Sekunde ist, gibt es immer noch eine Art Durchschnittswert. Tatsächlich hatten Sie ständig Anfragen, diese werden schnell ausgeführt, in 100 ms pro Sekunde, und das ist normal. Weil ClickHouse versucht, die Anforderung so schnell wie möglich auszuführen. Er versucht überhaupt nicht, Ihre Prozessoren vollständig und ständig zu nutzen und zu überhitzen.

Schauen wir uns das etwas genauer an, eine etwas komplizierte Option. Es gibt eine Abfrage mit einem Ausdruck in der Unterabfrage. Innerhalb der Unterabfrage haben wir 100 Millionen Zufallszahlen. Und wir filtern nur nach diesem Ergebnis.
Wir sehen so ein Bild. Übrigens, wer wird sagen, mit welchem Werkzeug ich dieses wundervolle Bild sehen kann? Absolut wahr - perf. Ich bin sehr froh, dass Sie das wissen.
Ich öffnete Perf und dachte, dass ich jetzt alles verstehe. Ich öffne die Assembler-Liste. Dort schrieb ich, wie oft die Ausführung des Programms auf einer bestimmten Anweisung erfolgte, dh wie oft es einen Anweisungszeiger gab. Hier sind die Zahlen in Prozent angegeben, und es wird geschrieben, dass fast 90% der Zeit, in der der Testbefehl% edx,% edx ausgeführt wurde, vier Bytes auf Null überprüft wurden.
Die Frage ist: Warum kann ein Prozessor so lange brauchen, um einfach vier Bytes mit Null zu vergleichen? (Antworten aus dem Publikum ...) Es gibt keinen Rest der Aufteilung. Es gibt Bitverschiebungen, dann gibt es einen crc32q-Befehl, aber als ob der Befehlszeiger niemals darauf passiert. Und Zufallszahlengenerierung ist nicht in dieser Liste. Es gab eine separate Funktion, die sehr gut optimiert ist und nicht langsamer wird. Hier verlangsamt sich etwas anderes. Die Codeausführung stoppt bei dieser Anweisung und verbringt viel Zeit. Leerlaufschleife? Nein. Warum sollte ich leere Schleifen einfügen? Wenn ich die Idle-Schleife einfügen würde, wäre dies auch in perf sichtbar. Es gibt keine Division durch Null, es gibt einfach einen Vergleich mit Null.
Der Prozessor hat eine Pipeline, er kann mehrere Befehle parallel ausführen. Und wenn sich der Befehlszeiger an einer Stelle befindet, bedeutet dies überhaupt nicht, dass er diesen Befehl ausführt. Vielleicht wartet er auf andere Anweisungen.
Wir haben eine Hash-Tabelle, um zu überprüfen, ob eine bestimmte Anzahl in einem Satz vorkommt. Dazu führen wir eine Suche im Speicher durch. Wenn wir eine Suche im Speicher durchführen, tritt ein Cache-Fehler auf, da die Hash-Tabelle 100 Millionen Zahlen enthält und nicht garantiert werden kann, dass sie in einen Cache passt. Um den Nullprüfbefehl auszuführen, sollten diese Daten bereits aus dem Speicher geladen sein. Und wir warten, bis sie geladen sind.

Jetzt die nächste Ressource, etwas komplexer - Laufwerke. SSDs werden manchmal auch als Laufwerke bezeichnet, obwohl dies nicht ganz richtig ist. In diesem Beispiel werden auch SSDs enthalten sein.
Wir öffnen zum Beispiel iostat, es zeigt eine Auslastung von 100%.
Bei Konferenzen kommt es häufig vor, dass der Redner auf die Bühne geht und mit Pathos sagt: „Datenbanken stoßen immer an die Festplatte. Aus diesem Grund haben wir eine In-Memory-Datenbank erstellt. Sie wird nicht langsamer. " Wenn sich eine Person Ihnen nähert und dies sagt, können Sie sie sicher senden. Es wird einige Probleme geben - Sie sagen, ich habe es gelöst. :) :)
Angenommen, ein Programm ruht auf Datenträgern, die Auslastung beträgt 100. Dies bedeutet jedoch natürlich nicht, dass wir Datenträger optimal verwenden.
Ein typisches Beispiel ist, wenn Sie nur viel Direktzugriff haben. Selbst wenn der Zugriff sequentiell erfolgt, lesen Sie die Datei einfach nacheinander, sie kann jedoch mehr oder weniger optimal sein.
Sie haben beispielsweise ein RAID-Array, mehrere Geräte, z. B. 8 Festplatten. Und Sie lesen nur nacheinander ohne Vorauslesen mit einer Puffergröße von 1 MB, und die Blockgröße in Ihrem Streifen in RAID beträgt ebenfalls 1 MB. Dann wird jeder Messwert von einem Gerät abgerufen. Oder, wenn nicht ausgerichtet, von zwei Geräten. Ein halbes Megabyte wird irgendwohin gehen, ein weiteres halbes Megabyte irgendwohin und so weiter - die Festplatten werden der Reihe nach verwendet: eine, dann eine andere, dann eine dritte.
Es muss vorher gelesen werden. Wenn Sie O_DIRECT haben, vergrößern Sie den Puffer. Das heißt, die Regel lautet: 8 Festplatten, Blockgröße 1 MB, stellen Sie die Puffergröße auf mindestens 8 MB ein. Dies funktioniert jedoch nur dann optimal, wenn der Messwert ausgerichtet ist. Und wenn es nicht ausgerichtet ist, gibt es zuerst zusätzliche Teile, und Sie müssen mehr setzen, multiplizieren Sie mit ein paar mehr.
Oder Sie haben beispielsweise RAID 10. Mit welcher Geschwindigkeit können Sie von RAID 10 lesen - zum Beispiel von 8 Festplatten? Was wird der Vorteil sein? Vierfach, weil es einen Spiegel gibt, oder achtfach? Tatsächlich hängt es davon ab, wie das RAID erstellt wird und mit welcher Anordnung von Blöcken in Streifen.
Wenn Sie mdadm unter Linux verwenden, können Sie dort Nah- und Fernlayout angeben, wobei Nah zum Schreiben und Fern zum Lesen besser ist.
Ich empfehle immer die Verwendung eines Fernlayouts, da das Schreiben in die Analysedatenbank in der Regel zeitlich nicht so kritisch ist - auch wenn viel mehr geschrieben als gelesen wird. Dies geschieht durch einen Hintergrundprozess. Aber wenn Sie lesen, müssen Sie es so schnell wie möglich fertigstellen. Daher ist es besser, RAID für das Lesen zu optimieren, indem Sie das Fernlayout festlegen.
Glücklicherweise stellt mdadm Sie unter Linux standardmäßig auf nahezu Layout ein und Sie erhalten nur die Hälfte der Leistung. Es gibt viele solcher Rechen.
Ein weiterer schrecklicher Rake ist RAID 5 oder RAID 6. Dort lässt sich alles durch sequentielles Lesen und Schreiben gut skalieren. In RAID 5 ist die Multiplizität "die Anzahl der Geräte minus eins". Dies lässt sich auch bei zufälligen Lesungen gut skalieren, bei zufälligen Lesungen jedoch nicht. Machen Sie eine Aufzeichnung an einem beliebigen Ort, und Sie müssen Daten von allen anderen Datenträgern lesen, sie speichern (XOR - ca. Ed.) Und an einen anderen Ort schreiben. Dafür wird ein bestimmter Streifen-Cache verwendet, ein schrecklicher Rechen. Unter Linux ist es standardmäßig so, dass Sie RAID 5 erstellen und es für Sie langsamer wird. Und Sie werden denken, dass RAID 5 immer langsamer wird, weil dies verständlich ist. Tatsächlich liegt der Grund jedoch in der falschen Einrichtung.
Ein weiteres Beispiel. Sie lesen von einer SSD und haben sich eine gute SSD gekauft. In der Spezifikation stehen 300.000 zufällige Lesevorgänge pro Sekunde. Und aus irgendeinem Grund können Sie es nicht tun. Und Sie denken - ja, sie liegen alle in ihren Spezifikationen, so etwas gibt es nicht. Alle diese Messungen müssen jedoch parallel und mit maximaler Parallelität durchgeführt werden. Die einzige Möglichkeit, dies optimal zu tun, ist die Verwendung von asynchroner E / A, die mithilfe der Systemaufrufe io_submit, io_getevents, io_setup usw. implementiert wird.
Übrigens, wenn Sie die Daten auf der Festplatte speichern, müssen Sie sie immer komprimieren. Ich werde ein Beispiel aus der Praxis geben. Eine Person hat uns im ClickHouse-
Support-Chat kontaktiert und gesagt:
- ClickHouse komprimiert die Daten. Ich sehe, es liegt auf dem Prozessor. Ich habe sehr schnelle NVMe-SSDs, sie haben eine Lesegeschwindigkeit von mehreren Gigabyte pro Sekunde. Ist es möglich, die Komprimierung in ClickHouse irgendwie zu deaktivieren?
"Nein, auf keinen Fall", sage ich. - Sie müssen die Daten komprimiert halten.
- Hören wir auf, es wird nur einen anderen Komprimierungsalgorithmus geben, der nichts bewirkt.
- Einfach. Geben Sie diese Buchstaben in diese Codezeile ein.
"In der Tat ist alles sehr einfach", antwortete er einen Tag später. - Ich habe gemacht.
- Wie stark hat sich die Leistung verändert?
"Fehler beim Testen", schrieb er einen weiteren Tag später. - Es sind zu viele Daten vorhanden. Sie passen nicht mehr auf SSDs.
Lassen Sie uns nun sehen, wie das Lesen von der Festplatte aussehen könnte. Wir starten dstat, es zeigt die Lesegeschwindigkeit.
Das erste Beispiel für dstat und iostat Hier ist die gelesene Spalte - 300 MB / s. Wir lesen von Scheiben. Es ist viel oder wenig - ich weiß es nicht.
Jetzt starte ich iostat, um dies zu überprüfen. Hier sehen Sie die Aufschlüsselung nach Gerät. Ich habe RAID, MD2 und acht Festplatten. Jeder von ihnen zeigt Recycling, es erreicht nicht einmal 100% (50-60%). Das Wichtigste ist jedoch, dass ich von jeder Festplatte nur mit einer Geschwindigkeit von 20-30 MB / s lese. Und seit meiner Kindheit erinnerte ich mich an die Regel, dass man irgendwo ab 100 MB / s von der Festplatte lesen kann. Aus irgendeinem Grund hat sich daran immer noch nicht viel geändert.
Zweites Beispiel für dstat und iostat Hier ist ein weiteres Beispiel. Lesen ist optimaler. Ich führe dstat aus und habe eine Lesegeschwindigkeit von 1 GB / s von diesem RAID 5 von acht Laufwerken. Was zeigt iostat? Ja, fast 1 GB / s.
Jetzt sind die Laufwerke endlich zu 100% geladen. Aus irgendeinem Grund sind zwei zu 100% und der Rest zu 95%. Wahrscheinlich sind sie noch etwas anders. Aber mit jedem von ihnen lese ich 150 MB / s, noch cooler als es sein kann. Was ist der Unterschied? Im ersten Fall lese ich mit unzureichender Puffergröße in unzureichenden Stücken. Es ist einfach, ich sage dir gemeinsame Wahrheiten.
Übrigens, wenn Sie der Meinung sind, dass die Daten für die Analysedatenbank immer noch nicht komprimiert werden müssen, d. H. Ein Bericht von der HighLoad ++ Sibirien-Konferenz (
Habrastatie basierend auf dem Bericht -
ungefähr ). Die Organisatoren beschlossen, die Hardcore-Berichte in Nowosibirsk zu erstellen.

Das nächste Beispiel ist Speicher. Fortsetzung der gemeinsamen Wahrheiten. Erstens, unter Linux, sehen Sie nie, welche kostenlosen Shows. Für diejenigen, die zuschauen, haben sie speziell die Website linuxatemyram.com erstellt. Komm rein, es wird eine Erklärung geben. Sie müssen sich auch nicht die Menge des virtuellen Speichers ansehen, denn was ist der Unterschied, wie viel Adressraum hat das Programm zugewiesen? Sehen Sie sich an, wie viel physischer Speicher verwendet wird.
Und noch ein Rechen, mit dem nicht einmal klar ist, wie man kämpft. Denken Sie daran: Die Tatsache, dass Allokatoren dem System häufig keinen Speicher geben möchten, ist normal. Sie haben mmap gemacht, aber munmap nicht mehr. Der Speicher kehrt nicht zum System zurück. Das Programm denkt - ich weiß besser, wie ich den Speicher nutzen werde. Ich werde es mir selbst überlassen. Weil die Systemaufrufe mmap und munmap ziemlich langsam sind. Ändern des Adressraums, Leeren der TLB-Caches des Prozessors - am besten nicht. Das Betriebssystem hat jedoch weiterhin die Möglichkeit, Speicher mithilfe des madvise-Systemaufrufs korrekt freizugeben. Der Adressraum bleibt erhalten, aber der Speicher kann physisch entladen werden.
Aktivieren Sie niemals den Austausch auf Produktionsservern mit Datenbanken. Sie denken - es gibt nicht genug Speicher, ich werde Swap einschließen. Danach funktioniert die Anfrage nicht mehr. Es wird endlose Zeit knacken.

Mit einem Netzwerk zu typischen Rechen. Wenn Sie jedes Mal eine TCP-Verbindung erstellen, dauert es einige Zeit, bis die richtige Fenstergröße ausgewählt ist, da das TCP-Protokoll nicht weiß, wie schnell Daten übertragen werden müssen. Er passt sich dem an.
Oder stellen Sie sich vor, Sie übertragen eine Datei und haben eine große Latenz in Ihrem Netzwerk und einen anständigen Paketverlust. Dann ist es überhaupt nicht offensichtlich, ob es richtig ist, TCP zum Übertragen von Dateien zu verwenden. Ich denke, es ist falsch, da TCP Konsistenz garantiert. Auf der anderen Seite können Sie eine Hälfte der Datei und die andere gleichzeitig übertragen. Verwenden Sie mindestens mehrere TCP-Verbindungen oder verwenden Sie TCP überhaupt nicht für die Datenübertragung. , , , TCP . .
100- , . 10 -, , , . . .

? — . , , , 10 . , .

: « - » — . iotop, , , iops.
, . .
top -, , clickHouse-server - , - . , , Shift+H, . , ClickHouse . ParalInputsProc, . BackgrProcPool — merges . , .
? ClickHouse, , . BackgroundProcessingPool. 15 . 16 1, 1 — . 16? , Linux — , : «16 . ». :) :)
clickhouse-benchmark. clickhouse-client. , clickhouse-client, . - . .
: clickhouse-benchmark + perf top . clickhouse-benchmark, , , , , . peft top. peft top, . , - -, uniq: UniquesHashSet. . , . , .
, , . — -. , , XOR - . -. - -. , -.
, , crc32q. , , - , - .
, ClickHouse. , , . ClickHouse.

. , — , SHOW PROCESSLIST. . , SELECT * FROM system processes. : , , . ClickHouse top.
ClickHouse ? background-. Background- — merges. , merges , SELECT * FROM system.merges.
, . -. . — ClickHouse. . , , . , . - traf_testing. Was ist das? , , . ClickHouse .

. , . , , , , . query_log. — , - , SELECT , - . query_log , . - . — , . : .
, , — merge, inserts, . part_log. , .

query_log clickhouse-benchmark. select , , stdin clickhouse-benchmark.
query_log - , .

, , . . SET send_logs_level = 'trace', , .
, . , 98%. , . Es ist sehr einfach. SET send_logs_level = 'trace', , . - : merging aggregated data, . 1% . , .
, , query_log.
. SELECT * FROM system.query_log . . , , , query_log. . — , , , . .

ClickHouse . — system.events, system.metrics system.asynchronous_metrics. Events — , , . 100 . — 10 . system.metrics — . , 10 , 10 .
system.asynchronous_metrics , . . — . , system.asynchronous_metrics — , - . , .
, . SHOW PROCESSLIST . query_log, .

, . , . , . , , . , Linux, . Linux . , . , . .
, OSReadChars OSReadBytes. Wie unterscheiden sie sich? , , , . , . , , , . , - , .
, . - . , 40 , 6,7 . . , ,
. , , .
, 1,3 , 5 . Warum? , — page cache. ?
. . , , . . : 3,2 , — 2,5 . , , , . Warum? -, : read ahead. , — ? -, — 4 , , 512 KB. . , . , - read ahead.

. . , . , , ReadBytes — , . 3 , 3 . , , .
— IOWait. 87 . 7 , IOWait — 87. ? — . . , , 87 . , - .
— CPUWait. , , , . - — , . CPU. CPU. - , . — , , user space. , - . Na ja, okay.
— , Linux. - , . , , .
Und jetzt das Fortgeschrittenste, was wir haben: query_thread_log. Damit können Sie verstehen, wofür jeder Thread der Abfrageausführung Zeit verschwendet hat.Ich suche nach meiner Anfrage, wähle sie mit query_id aus und gebe die Metrik "Die im Benutzerraum verbrachte Prozessorzeit" an. Hier sind unsere Streams. Für die parallele Verarbeitung der Anfrage wurden 16 Threads zugewiesen. Jeder von ihnen verbrachte 800 ms. Und dann wurden weitere 16 Threads für die Zusammenführung des Zustands der Aggregatfunktionen zugewiesen, für die jeweils 0,25 s aufgewendet wurden. Jetzt kann ich genau verstehen, was jede Anfrage Zeit gekostet hat.Videobericht zu HighLoad ++: