1,1 Milliarden Taxifahrten: 108-Kern-ClickHouse-Cluster

Eine Übersetzung des Artikels wurde speziell für Studenten des Data Engineer- Kurses erstellt.





ClickHouse ist eine Open Source- Spaltendatenbank . Dies ist eine großartige Umgebung, in der Hunderte von Analysten schnell detaillierte Daten anfordern können, selbst wenn pro Tag zig Milliarden neuer Einträge eingeführt werden. Die Infrastrukturkosten für die Unterstützung eines solchen Systems können 100.000 US-Dollar pro Jahr erreichen und je nach Nutzung möglicherweise halb so hoch sein. Irgendwann enthielt die Installation von Yandex.Metrica ClickHouse 10 Billionen Einträge. Neben Yandex war ClickHouse auch mit Bloomberg und Cloudflare erfolgreich.

Vor zwei Jahren habe ich eine vergleichende Analyse von Datenbanken mit einem einzigen Computer durchgeführt und es wurde die schnellste kostenlose Datenbanksoftware, die ich je gesehen habe. Seitdem haben Entwickler nicht aufgehört, Funktionen hinzuzufügen, einschließlich der Unterstützung für Kafka-, HDFS- und ZStandard-Komprimierung. Letztes Jahr haben sie Unterstützung für kaskadierende Komprimierungsmethoden hinzugefügt, und Delta-Delta- Codierung wurde möglich. Beim Komprimieren von Zeitreihendaten können Messwerte mithilfe der Delta-Codierung gut komprimiert werden. Es ist jedoch besser, die Delta-Delta-Codierung für Zähler zu verwenden. Eine gute Komprimierung ist zum Schlüssel für die Leistung von ClickHouse geworden.

ClickHouse besteht mit Ausnahme von Bibliotheken von Drittanbietern aus 170.000 Zeilen C ++ - Code und ist eine der kleinsten Codedatenbanken für verteilte Datenbanken. Zum Vergleich: SQLite unterstützt keine Verteilung und besteht aus 235.000 Codezeilen in der Sprache C. Zum Zeitpunkt dieses Schreibens haben 207 Ingenieure zu ClickHouse beigetragen, und die Intensität der Festschreibungen hat in letzter Zeit zugenommen.

Im März 2017 startete ClickHouse ein Änderungsprotokoll , um die Entwicklung auf einfache Weise zu verfolgen. Sie teilen auch die monolithische Dokumentationsdatei in eine Markdown-basierte Dateihierarchie auf. Probleme und Funktionen werden über GitHub verfolgt, und insgesamt ist diese Software in den letzten Jahren viel zugänglicher geworden.

In diesem Artikel werde ich einen Blick auf die Leistung von ClickHouse-Clustern unter AWS EC2 mit 36-Kern-Prozessoren und einem NVMe-Laufwerk werfen.
UPDATE: Eine Woche nach der ersten Veröffentlichung dieses Beitrags habe ich den Test mit einer verbesserten Konfiguration erneut ausgeführt und viel bessere Ergebnisse erzielt. Dieser Beitrag wurde aktualisiert, um diese Änderungen widerzuspiegeln.

Starten eines AWS EC2-Clusters


Ich werde drei Instanzen von c5d.9xlarge EC2 für diesen Beitrag verwenden. Jede von ihnen enthält 36 virtuelle CPUs, 72 GB RAM, 900 GB NVMe-SSD und unterstützt ein 10-Gigabit-Netzwerk. Sie kosten in der Region eu-west-1 jeweils 1.962 USD / Stunde, wenn sie auf Anfrage eingeführt werden. Ich werde Ubuntu Server 16.04 LTS als Betriebssystem verwenden.

Die Firewall ist so konfiguriert, dass jeder Computer ohne Einschränkungen miteinander kommunizieren kann und nur meine IPv4-Adresse im SSH-Cluster auf die Whitelist gesetzt wird.

Gebrauchsfertiges NVMe


Damit ClickHouse funktioniert, erstelle ich auf jedem Server im NVMe-Laufwerk ein EXT4-Dateisystem.

$ sudo mkfs -t ext4 /dev/nvme1n1 $ sudo mkdir /ch $ sudo mount /dev/nvme1n1 /ch 

Nachdem alles konfiguriert wurde, können Sie den Einhängepunkt und 783 GB verfügbaren Speicherplatz in jedem der Systeme anzeigen.

 $ lsblk 

 NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT loop0 7:0 0 87.9M 1 loop /snap/core/5742 loop1 7:1 0 16.5M 1 loop /snap/amazon-ssm-agent/784 nvme0n1 259:1 0 8G 0 disk └─nvme0n1p1 259:2 0 8G 0 part / nvme1n1 259:0 0 838.2G 0 disk /ch 

 $ df -h 

 Filesystem Size Used Avail Use% Mounted on udev 35G 0 35G 0% /dev tmpfs 6.9G 8.8M 6.9G 1% /run /dev/nvme0n1p1 7.7G 967M 6.8G 13% / tmpfs 35G 0 35G 0% /dev/shm tmpfs 5.0M 0 5.0M 0% /run/lock tmpfs 35G 0 35G 0% /sys/fs/cgroup /dev/loop0 88M 88M 0 100% /snap/core/5742 /dev/loop1 17M 17M 0 100% /snap/amazon-ssm-agent/784 tmpfs 6.9G 0 6.9G 0% /run/user/1000 /dev/nvme1n1 825G 73M 783G 1% /ch 

Der Datensatz, den ich in diesem Test verwenden werde, ist ein Datendump, den ich aus 1,1 Milliarden Taxifahrten in New York in sechs Jahren erstellt habe. Der Billion Taxi- Blog auf Redshift beschreibt, wie ich diesen Datensatz gesammelt habe. Sie werden in AWS S3 gespeichert, daher konfiguriere ich die AWS-Befehlszeilenschnittstelle mithilfe meines Zugriffs und meiner privaten Schlüssel.

 $ sudo apt update $ sudo apt install awscli $ aws configure 

Ich werde das Limit für die Anzahl gleichzeitiger Client-Anforderungen auf 100 setzen, damit Dateien schneller als mit Standardeinstellungen geladen werden.

 $ aws configure set \ default.s3.max_concurrent_requests \ 100 

Ich werde den Datensatz für Taxifahrten von AWS S3 herunterladen und auf dem NVMe-Laufwerk auf dem ersten Server speichern. Dieser Datensatz hat eine Größe von ~ 104 GB im GZIP-komprimierten CSV-Format.

 $ sudo mkdir -p /ch/csv $ sudo chown -R ubuntu /ch/csv $ aws s3 sync s3://<bucket>/csv /ch/csv 

Installieren Sie ClickHouse


Ich werde die OpenJDK-Distribution für Java 8 installieren, da Apache ZooKeeper ausgeführt werden muss, was für die verteilte Installation von ClickHouse auf allen drei Computern erforderlich ist.

 $ sudo apt update $ sudo apt install \ openjdk-8-jre \ openjdk-8-jdk-headless 

Dann habe ich die Umgebungsvariable JAVA_HOME .

 $ sudo vi /etc/profile export JAVA_HOME=/usr $ source /etc/profile 

Dann werde ich das Paketverwaltungssystem in Ubuntu verwenden, um ClickHouse 18.16.1, blances und ZooKeeper auf allen drei Computern zu installieren.

 $ sudo apt-key adv \ --keyserver hkp://keyserver.ubuntu.com:80 \ --recv E0C56BD4 $ echo "deb http://repo.yandex.ru/clickhouse/deb/stable/ main/" | \ sudo tee /etc/apt/sources.list.d/clickhouse.list $ sudo apt-get update 

 $ sudo apt install \ clickhouse-client \ clickhouse-server \ glances \ zookeeperd 

Ich werde ein Verzeichnis für ClickHouse erstellen und auch einige Konfigurationsüberschreibungen auf allen drei Servern vornehmen.

 $ sudo mkdir /ch/clickhouse $ sudo chown -R clickhouse /ch/clickhouse $ sudo mkdir -p /etc/clickhouse-server/conf.d $ sudo vi /etc/clickhouse-server/conf.d/taxis.conf 

Dies sind die Konfigurationsüberschreibungen, die ich verwenden werde.

 <?xml version="1.0"?> <yandex> <listen_host>0.0.0.0</listen_host> <path>/ch/clickhouse/</path> 

  <remote_servers> <perftest_3shards> <shard> <replica> <host>172.30.2.192</host> <port>9000</port> </replica> </shard> <shard> <replica> <host>172.30.2.162</host> <port>9000</port> </replica> </shard> <shard> <replica> <host>172.30.2.36</host> <port>9000</port> </replica> </shard> </perftest_3shards> </remote_servers> 

  <zookeeper-servers> <node> <host>172.30.2.192</host> <port>2181</port> </node> <node> <host>172.30.2.162</host> <port>2181</port> </node> <node> <host>172.30.2.36</host> <port>2181</port> </node> </zookeeper-servers> 

  <macros> <shard>03</shard> <replica>01</replica> </macros> </yandex> 

Dann werde ich ZooKeeper und den ClickHouse-Server auf allen drei Computern ausführen.

 $ sudo /etc/init.d/zookeeper start $ sudo service clickhouse-server start 

Laden von Daten in ClickHouse


Auf dem ersten Server werde ich eine Fahrten-Tabelle erstellen, in der ein Datensatz von Taxifahrten mit der Log-Engine gespeichert wird.

 $ clickhouse-client --host=0.0.0.0 CREATE TABLE trips ( trip_id UInt32, vendor_id String, pickup_datetime DateTime, dropoff_datetime Nullable(DateTime), store_and_fwd_flag Nullable(FixedString(1)), rate_code_id Nullable(UInt8), pickup_longitude Nullable(Float64), pickup_latitude Nullable(Float64), dropoff_longitude Nullable(Float64), dropoff_latitude Nullable(Float64), passenger_count Nullable(UInt8), trip_distance Nullable(Float64), fare_amount Nullable(Float32), extra Nullable(Float32), mta_tax Nullable(Float32), tip_amount Nullable(Float32), tolls_amount Nullable(Float32), ehail_fee Nullable(Float32), improvement_surcharge Nullable(Float32), total_amount Nullable(Float32), payment_type Nullable(String), trip_type Nullable(UInt8), pickup Nullable(String), dropoff Nullable(String), cab_type Nullable(String), precipitation Nullable(Int8), snow_depth Nullable(Int8), snowfall Nullable(Int8), max_temperature Nullable(Int8), min_temperature Nullable(Int8), average_wind_speed Nullable(Int8), pickup_nyct2010_gid Nullable(Int8), pickup_ctlabel Nullable(String), pickup_borocode Nullable(Int8), pickup_boroname Nullable(String), pickup_ct2010 Nullable(String), pickup_boroct2010 Nullable(String), pickup_cdeligibil Nullable(FixedString(1)), pickup_ntacode Nullable(String), pickup_ntaname Nullable(String), pickup_puma Nullable(String), dropoff_nyct2010_gid Nullable(UInt8), dropoff_ctlabel Nullable(String), dropoff_borocode Nullable(UInt8), dropoff_boroname Nullable(String), dropoff_ct2010 Nullable(String), dropoff_boroct2010 Nullable(String), dropoff_cdeligibil Nullable(String), dropoff_ntacode Nullable(String), dropoff_ntaname Nullable(String), dropoff_puma Nullable(String) ) ENGINE = Log; 

Dann entpacke ich jede der CSV-Dateien und lade sie in eine Auslösetabelle. Das Folgende ist in 55 Minuten und 10 Sekunden erledigt. Nach diesem Vorgang betrug die Datenverzeichnisgröße 134 GB.

 $ time (for FILENAME in /ch/csv/trips_x*.csv.gz; do echo $FILENAME gunzip -c $FILENAME | \ clickhouse-client \ --host=0.0.0.0 \ --query="INSERT INTO trips FORMAT CSV" done) 

Die Importgeschwindigkeit betrug 155 MB unkomprimierten CSV-Inhalt pro Sekunde. Ich vermute, dass dies auf einen Engpass bei der GZIP-Dekompression zurückzuführen ist. Es war möglicherweise schneller, alle gzip-Dateien parallel mit xargs zu entpacken und dann die entpackten Daten zu laden. Im Folgenden wird beschrieben, was während des CSV-Importvorgangs gemeldet wurde.

 $ sudo glances 

 ip-172-30-2-200 (Ubuntu 16.04 64bit / Linux 4.4.0-1072-aws) Uptime: 0:11:42 CPU 8.2% nice: 0.0% LOAD 36-core MEM 9.8% active: 5.20G SWAP 0.0% user: 6.0% irq: 0.0% 1 min: 2.24 total: 68.7G inactive: 61.0G total: 0 system: 0.9% iowait: 1.3% 5 min: 1.83 used: 6.71G buffers: 66.4M used: 0 idle: 91.8% steal: 0.0% 15 min: 1.01 free: 62.0G cached: 61.6G free: 0 NETWORK Rx/s Tx/s TASKS 370 (507 thr), 2 run, 368 slp, 0 oth sorted automatically by cpu_percent, flat view ens5 136b 2Kb lo 343Mb 343Mb CPU% MEM% VIRT RES PID USER NI S TIME+ IOR/s IOW/s Command 100.4 1.5 1.65G 1.06G 9909 ubuntu 0 S 1:01.33 0 0 clickhouse-client --host=0.0.0.0 --query=INSERT INTO trips FORMAT CSV DISK I/OR/s W/s 85.1 0.0 4.65M 708K 9908 ubuntu 0 R 0:50.60 32M 0 gzip -d -c /ch/csv/trips_xac.csv.gz loop0 0 0 54.9 5.1 8.14G 3.49G 8091 clickhous 0 S 1:44.23 0 45M /usr/bin/clickhouse-server --config=/etc/clickhouse-server/config.xml loop1 0 0 4.5 0.0 0 0 319 root 0 S 0:07.50 1K 0 kworker/u72:2 nvme0n1 0 3K 2.3 0.0 91.1M 28.9M 9912 root 0 R 0:01.56 0 0 /usr/bin/python3 /usr/bin/glances nvme0n1p1 0 3K 0.3 0.0 0 0 960 root -20 S 0:00.10 0 0 kworker/28:1H nvme1n1 32.1M 495M 0.3 0.0 0 0 1058 root -20 S 0:00.90 0 0 kworker/23:1H 

Ich werde Speicherplatz auf dem NVMe-Laufwerk freigeben, indem ich die CSV-Quelldateien lösche, bevor ich fortfahre.

 $ sudo rm -fr /ch/csv 

In Spaltenform konvertieren


Die Log ClickHouse-Engine speichert Daten in einem zeilenorientierten Format. Um Daten schneller anzufordern, konvertiere ich sie mithilfe der MergeTree-Engine in das Spaltenformat.

 $ clickhouse-client --host=0.0.0.0 

Das Folgende ist in 34 Minuten und 50 Sekunden erledigt. Nach diesem Vorgang betrug die Datenverzeichnisgröße 237 GB.

 CREATE TABLE trips_mergetree ENGINE = MergeTree(pickup_date, pickup_datetime, 8192) AS SELECT trip_id, CAST(vendor_id AS Enum8('1' = 1, '2' = 2, 'CMT' = 3, 'VTS' = 4, 'DDS' = 5, 'B02512' = 10, 'B02598' = 11, 'B02617' = 12, 'B02682' = 13, 'B02764' = 14)) AS vendor_id, toDate(pickup_datetime) AS pickup_date, ifNull(pickup_datetime, toDateTime(0)) AS pickup_datetime, toDate(dropoff_datetime) AS dropoff_date, ifNull(dropoff_datetime, toDateTime(0)) AS dropoff_datetime, assumeNotNull(store_and_fwd_flag) AS store_and_fwd_flag, assumeNotNull(rate_code_id) AS rate_code_id, assumeNotNull(pickup_longitude) AS pickup_longitude, assumeNotNull(pickup_latitude) AS pickup_latitude, assumeNotNull(dropoff_longitude) AS dropoff_longitude, assumeNotNull(dropoff_latitude) AS dropoff_latitude, assumeNotNull(passenger_count) AS passenger_count, assumeNotNull(trip_distance) AS trip_distance, assumeNotNull(fare_amount) AS fare_amount, assumeNotNull(extra) AS extra, assumeNotNull(mta_tax) AS mta_tax, assumeNotNull(tip_amount) AS tip_amount, assumeNotNull(tolls_amount) AS tolls_amount, assumeNotNull(ehail_fee) AS ehail_fee, assumeNotNull(improvement_surcharge) AS improvement_surcharge, assumeNotNull(total_amount) AS total_amount, assumeNotNull(payment_type) AS payment_type_, assumeNotNull(trip_type) AS trip_type, pickup AS pickup, pickup AS dropoff, CAST(assumeNotNull(cab_type) AS Enum8('yellow' = 1, 'green' = 2)) AS cab_type, precipitation AS precipitation, snow_depth AS snow_depth, snowfall AS snowfall, max_temperature AS max_temperature, min_temperature AS min_temperature, average_wind_speed AS average_wind_speed, pickup_nyct2010_gid AS pickup_nyct2010_gid, pickup_ctlabel AS pickup_ctlabel, pickup_borocode AS pickup_borocode, pickup_boroname AS pickup_boroname, pickup_ct2010 AS pickup_ct2010, pickup_boroct2010 AS pickup_boroct2010, pickup_cdeligibil AS pickup_cdeligibil, pickup_ntacode AS pickup_ntacode, pickup_ntaname AS pickup_ntaname, pickup_puma AS pickup_puma, dropoff_nyct2010_gid AS dropoff_nyct2010_gid, dropoff_ctlabel AS dropoff_ctlabel, dropoff_borocode AS dropoff_borocode, dropoff_boroname AS dropoff_boroname, dropoff_ct2010 AS dropoff_ct2010, dropoff_boroct2010 AS dropoff_boroct2010, dropoff_cdeligibil AS dropoff_cdeligibil, dropoff_ntacode AS dropoff_ntacode, dropoff_ntaname AS dropoff_ntaname, dropoff_puma AS dropoff_puma FROM trips; 

So sah die Blickausgabe während der Operation aus:

 ip-172-30-2-200 (Ubuntu 16.04 64bit / Linux 4.4.0-1072-aws) Uptime: 1:06:09 CPU 10.3% nice: 0.0% LOAD 36-core MEM 16.1% active: 13.3G SWAP 0.0% user: 7.9% irq: 0.0% 1 min: 1.87 total: 68.7G inactive: 52.8G total: 0 system: 1.6% iowait: 0.8% 5 min: 1.76 used: 11.1G buffers: 71.8M used: 0 idle: 89.7% steal: 0.0% 15 min: 1.95 free: 57.6G cached: 57.2G free: 0 NETWORK Rx/s Tx/s TASKS 367 (523 thr), 1 run, 366 slp, 0 oth sorted automatically by cpu_percent, flat view ens5 1Kb 8Kb lo 2Kb 2Kb CPU% MEM% VIRT RES PID USER NI S TIME+ IOR/s IOW/s Command 241.9 12.8 20.7G 8.78G 8091 clickhous 0 S 30:36.73 34M 125M /usr/bin/clickhouse-server --config=/etc/clickhouse-server/config.xml DISK I/OR/s W/s 2.6 0.0 90.4M 28.3M 9948 root 0 R 1:18.53 0 0 /usr/bin/python3 /usr/bin/glances loop0 0 0 1.3 0.0 0 0 203 root 0 S 0:09.82 0 0 kswapd0 loop1 0 0 0.3 0.1 315M 61.3M 15701 ubuntu 0 S 0:00.40 0 0 clickhouse-client --host=0.0.0.0 nvme0n1 0 3K 0.3 0.0 0 0 7 root 0 S 0:00.83 0 0 rcu_sched nvme0n1p1 0 3K 0.0 0.0 0 0 142 root 0 S 0:00.22 0 0 migration/27 nvme1n1 25.8M 330M 0.0 0.0 59.7M 1.79M 2764 ubuntu 0 S 0:00.00 0 0 (sd-pam) 

Im letzten Test wurden mehrere Spalten konvertiert und neu gezählt. Ich habe festgestellt, dass einige dieser Funktionen in diesem Datensatz nicht mehr ordnungsgemäß funktionieren. Um dieses Problem zu lösen, habe ich die unangemessenen Funktionen entfernt und die Daten ohne Konvertierung in detailliertere Typen heruntergeladen.

Cluster-Datenverteilung


Ich werde Daten auf alle drei Knoten des Clusters verteilen. Zunächst werde ich auf allen drei Maschinen eine Tabelle erstellen.

 $ clickhouse-client --host=0.0.0.0 

 CREATE TABLE trips_mergetree_third ( trip_id UInt32, vendor_id String, pickup_date Date, pickup_datetime DateTime, dropoff_date Date, dropoff_datetime Nullable(DateTime), store_and_fwd_flag Nullable(FixedString(1)), rate_code_id Nullable(UInt8), pickup_longitude Nullable(Float64), pickup_latitude Nullable(Float64), dropoff_longitude Nullable(Float64), dropoff_latitude Nullable(Float64), passenger_count Nullable(UInt8), trip_distance Nullable(Float64), fare_amount Nullable(Float32), extra Nullable(Float32), mta_tax Nullable(Float32), tip_amount Nullable(Float32), tolls_amount Nullable(Float32), ehail_fee Nullable(Float32), improvement_surcharge Nullable(Float32), total_amount Nullable(Float32), payment_type Nullable(String), trip_type Nullable(UInt8), pickup Nullable(String), dropoff Nullable(String), cab_type Nullable(String), precipitation Nullable(Int8), snow_depth Nullable(Int8), snowfall Nullable(Int8), max_temperature Nullable(Int8), min_temperature Nullable(Int8), average_wind_speed Nullable(Int8), pickup_nyct2010_gid Nullable(Int8), pickup_ctlabel Nullable(String), pickup_borocode Nullable(Int8), pickup_boroname Nullable(String), pickup_ct2010 Nullable(String), pickup_boroct2010 Nullable(String), pickup_cdeligibil Nullable(FixedString(1)), pickup_ntacode Nullable(String), pickup_ntaname Nullable(String), pickup_puma Nullable(String), dropoff_nyct2010_gid Nullable(UInt8), dropoff_ctlabel Nullable(String), dropoff_borocode Nullable(UInt8), dropoff_boroname Nullable(String), dropoff_ct2010 Nullable(String), dropoff_boroct2010 Nullable(String), dropoff_cdeligibil Nullable(String), dropoff_ntacode Nullable(String), dropoff_ntaname Nullable(String), dropoff_puma Nullable(String) ) ENGINE = MergeTree(pickup_date, pickup_datetime, 8192); 

Dann werde ich sicherstellen, dass der erste Server alle drei Knoten im Cluster sehen kann.

 SELECT * FROM system.clusters WHERE cluster = 'perftest_3shards' FORMAT Vertical; 


 Row 1: ────── cluster: perftest_3shards shard_num: 1 shard_weight: 1 replica_num: 1 host_name: 172.30.2.192 host_address: 172.30.2.192 port: 9000 is_local: 1 user: default default_database: 


 Row 2: ────── cluster: perftest_3shards shard_num: 2 shard_weight: 1 replica_num: 1 host_name: 172.30.2.162 host_address: 172.30.2.162 port: 9000 is_local: 0 user: default default_database: 

 Row 3: ────── cluster: perftest_3shards shard_num: 3 shard_weight: 1 replica_num: 1 host_name: 172.30.2.36 host_address: 172.30.2.36 port: 9000 is_local: 0 user: default default_database: 

Dann werde ich auf dem ersten Server eine neue Tabelle definieren, die auf dem trips_mergetree_third basiert und die verteilte Engine verwendet.

 CREATE TABLE trips_mergetree_x3 AS trips_mergetree_third ENGINE = Distributed(perftest_3shards, default, trips_mergetree_third, rand()); 

Dann kopiere ich die Daten aus der Tabelle basierend auf MergeTree auf alle drei Server. Das Folgende ist in 34 Minuten und 44 Sekunden erledigt.

 INSERT INTO trips_mergetree_x3 SELECT * FROM trips_mergetree; 

Nach dem obigen Vorgang gab ich ClickHouse 15 Minuten Zeit, um mich von der maximalen Speicherebene zu entfernen. Die Datenverzeichnisse waren auf jedem der drei Server 264 GB, 34 GB bzw. 33 GB groß.

ClickHouse Cluster Performance Assessment


Was ich als nächstes sah, war die schnellste Zeit, die ich sah, als ich jede Abfrage mehrmals in der Tabelle trips_mergetree_x3 .

 $ clickhouse-client --host=0.0.0.0 

Das Folgende wurde in 2,449 Sekunden abgeschlossen.

 SELECT cab_type, count(*) FROM trips_mergetree_x3 GROUP BY cab_type; 

Das Folgende wurde in 0,691 Sekunden abgeschlossen.

 SELECT passenger_count, avg(total_amount) FROM trips_mergetree_x3 GROUP BY passenger_count; 

Das Folgende wurde in 0. 582 Sekunden abgeschlossen.

 SELECT passenger_count, toYear(pickup_date) AS year, count(*) FROM trips_mergetree_x3 GROUP BY passenger_count, year; 

Das Folgende ist in 0,983 Sekunden abgeschlossen.

 SELECT passenger_count, toYear(pickup_date) AS year, round(trip_distance) AS distance, count(*) FROM trips_mergetree_x3 GROUP BY passenger_count, year, distance ORDER BY year, count(*) DESC; 

Zum Vergleich habe ich dieselben Abfragen in einer Tabelle durchgeführt, die auf MergeTree basiert und sich ausschließlich auf dem ersten Server befindet.

Leistungsbewertung eines ClickHouse-Knotens


Was ich als nächstes sah, war die schnellste Zeit, die ich sah, als ich jede Abfrage mehrmals in der Tabelle trips_mergetree_x3 .

Das Folgende ist in 0,241 Sekunden abgeschlossen.

 SELECT cab_type, count(*) FROM trips_mergetree GROUP BY cab_type; 

Das Folgende ist in 0,826 Sekunden abgeschlossen.

 SELECT passenger_count, avg(total_amount) FROM trips_mergetree GROUP BY passenger_count; 

Das Folgende ist in 1,209 Sekunden abgeschlossen.

 SELECT passenger_count, toYear(pickup_date) AS year, count(*) FROM trips_mergetree GROUP BY passenger_count, year; 

Folgendes wurde in 1,781 Sekunden abgeschlossen.

 SELECT passenger_count, toYear(pickup_date) AS year, round(trip_distance) AS distance, count(*) FROM trips_mergetree GROUP BY passenger_count, year, distance ORDER BY year, count(*) DESC; 

Reflexionen über die Ergebnisse


Dies ist das erste Mal, dass eine freie prozessorbasierte Datenbank in meinen Tests die GPU-Datenbank übertreffen konnte. Diese GPU-basierte Datenbank wurde seitdem zwei Mal überarbeitet, aber die Leistung, die ClickHouse auf einem Knoten zeigte, ist dennoch sehr beeindruckend.

Wenn Sie Abfrage 1 auf einer verteilten Engine ausführen, ist der Overhead gleichzeitig um eine Größenordnung höher. Ich hoffe, dass ich bei meinen Recherchen für diesen Beitrag etwas verpasst habe, da es schön wäre zu sehen, wie sich die Abfragezeit verringert, wenn ich dem Cluster weitere Knoten hinzufüge. Es ist jedoch bemerkenswert, dass bei anderen Abfragen die Produktivität um das Zweifache gesteigert wurde.

Es wäre schön, wenn ClickHouse so weiterentwickelt würde, dass Speicher und Computer getrennt werden könnten, damit sie unabhängig voneinander skalieren können. Die HDFS-Unterstützung, die letztes Jahr hinzugefügt wurde, könnte ein Schritt in diese Richtung sein. Wenn eine einzelne Anforderung durch Hinzufügen weiterer Knoten zum Cluster beschleunigt werden kann, ist die Zukunft dieser Software sehr vielversprechend.

Vielen Dank, dass Sie sich die Zeit genommen haben, diesen Beitrag zu lesen. Ich biete Beratung, Architektur und praktische Entwicklungsdienstleistungen für Kunden in Nordamerika und Europa. Wenn Sie besprechen möchten, wie meine Vorschläge Ihrem Unternehmen helfen können, kontaktieren Sie mich über LinkedIn .

Source: https://habr.com/ru/post/de463665/


All Articles