1.1 miliar perjalanan taksi: cluster ClickHouse 108-inti

Terjemahan artikel disiapkan khusus untuk mahasiswa kursus tersebut Insinyur Data.

1.1 miliar perjalanan taksi: cluster ClickHouse 108-inti

KlikRumah adalah database kolom sumber terbuka. Ini adalah lingkungan yang bagus di mana ratusan analis dapat dengan cepat menanyakan data terperinci, bahkan ketika puluhan miliar catatan baru dimasukkan setiap hari. Biaya infrastruktur untuk mendukung sistem tersebut bisa mencapai $100 per tahun, dan mungkin setengahnya tergantung pada penggunaan. Pada satu titik, instalasi ClickHouse dari Yandex Metrics berisi 10 triliun catatan. Selain Yandex, ClickHouse juga meraih kesuksesan dengan Bloomberg dan Cloudflare.

Dua tahun lalu saya habiskan analisis komparatif database menggunakan satu mesin, dan itu menjadi Tercepat perangkat lunak database gratis yang pernah saya lihat. Sejak itu, pengembang tidak berhenti menambahkan fitur, termasuk dukungan untuk kompresi Kafka, HDFS, dan ZStandard. Tahun lalu mereka menambahkan dukungan untuk metode kompresi berjenjang, dan delta-dari-delta pengkodean menjadi mungkin. Saat mengompresi data deret waktu, nilai pengukur dapat dikompresi dengan baik menggunakan pengkodean delta, tetapi untuk penghitung akan lebih baik menggunakan pengkodean delta-demi-delta. Kompresi yang baik menjadi kunci kinerja ClickHouse.

ClickHouse terdiri dari 170 ribu baris kode C++, tidak termasuk perpustakaan pihak ketiga, dan merupakan salah satu basis kode database terdistribusi terkecil. Sebagai perbandingan, SQLite tidak mendukung distribusi dan terdiri dari 235 ribu baris kode C. Saat tulisan ini dibuat, 207 insinyur telah berkontribusi pada ClickHouse, dan intensitas komitmen semakin meningkat akhir-akhir ini.

Pada bulan Maret 2017, ClickHouse mulai mengadakan log perubahan sebagai cara mudah untuk melacak perkembangan. Mereka juga memecah file dokumentasi monolitik menjadi hierarki file berbasis penurunan harga. Masalah dan fitur dilacak melalui GitHub, dan secara umum perangkat lunak ini menjadi lebih mudah diakses dalam beberapa tahun terakhir.

Pada artikel ini, saya akan melihat kinerja cluster ClickHouse di AWS EC2 menggunakan prosesor 36-core dan penyimpanan NVMe.

PEMBARUAN: Seminggu setelah pertama kali menerbitkan postingan ini, saya menjalankan ulang pengujian dengan konfigurasi yang ditingkatkan dan mencapai hasil yang jauh lebih baik. Posting ini telah diperbarui untuk mencerminkan perubahan ini.

Meluncurkan Klaster AWS EC2

Saya akan menggunakan tiga instance EC5 c9d.2xlarge untuk posting ini. Masing-masing berisi 36 CPU virtual, RAM 72 GB, penyimpanan NVMe SSD 900 GB, dan mendukung jaringan 10 Gigabit. Harganya masing-masing $1,962/jam di wilayah eu-west-1 jika dijalankan sesuai permintaan. Saya akan menggunakan Ubuntu Server 16.04 LTS sebagai sistem operasinya.

Firewall dikonfigurasi sehingga setiap mesin dapat berkomunikasi satu sama lain tanpa batasan, dan hanya alamat IPv4 saya yang masuk daftar putih oleh SSH di cluster.

Drive NVMe dalam kondisi kesiapan operasional

Agar ClickHouse berfungsi, saya akan membuat sistem file dalam format EXT4 pada drive NVMe di masing-masing server.

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

Setelah semuanya dikonfigurasi, Anda dapat melihat titik pemasangan dan ruang 783 GB yang tersedia di setiap sistem.

$ 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

Kumpulan data yang akan saya gunakan dalam pengujian ini adalah kumpulan data yang saya hasilkan dari 1.1 miliar perjalanan taksi yang dilakukan di New York City selama enam tahun. Di blog Satu Miliar Perjalanan Taksi di Redshift merinci bagaimana saya mengumpulkan kumpulan data ini. Mereka disimpan di AWS S3, jadi saya akan mengonfigurasi AWS CLI dengan akses dan kunci rahasia saya.

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

Saya akan menetapkan batas permintaan bersamaan klien menjadi 100 sehingga file diunduh lebih cepat daripada pengaturan default.

$ aws configure set 
    default.s3.max_concurrent_requests 
    100

Saya akan mengunduh kumpulan data naik taksi dari AWS S3 dan menyimpannya di drive NVMe di server pertama. Kumpulan data ini berukuran ~104 GB dalam format CSV terkompresi GZIP.

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

Instalasi ClickHouse

Saya akan menginstal distribusi OpenJDK untuk Java 8 karena diperlukan untuk menjalankan Apache ZooKeeper, yang diperlukan untuk instalasi terdistribusi ClickHouse di ketiga mesin.

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

Lalu saya mengatur variabel lingkungan JAVA_HOME.

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

Saya kemudian akan menggunakan sistem manajemen paket Ubuntu untuk menginstal ClickHouse 18.16.1, sekilas dan ZooKeeper di ketiga mesin.

$ 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

Saya akan membuat direktori untuk ClickHouse dan juga melakukan beberapa penggantian konfigurasi pada ketiga server.

$ 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

Ini adalah penggantian konfigurasi yang akan saya gunakan.

<?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>

Saya kemudian akan menjalankan ZooKeeper dan server ClickHouse di ketiga mesin.

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

Mengunggah data ke ClickHouse

Di server pertama saya akan membuat tabel perjalanan (trips), yang akan menyimpan kumpulan data perjalanan taksi menggunakan mesin Log.

$ 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;

Saya kemudian mengekstrak dan memuat setiap file CSV ke dalam tabel perjalanan (trips). Berikut ini selesai dalam 55 menit dan 10 detik. Setelah operasi ini, ukuran direktori data adalah 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)

Kecepatan impor konten CSV yang tidak terkompresi adalah 155 MB per detik. Saya menduga hal ini disebabkan oleh hambatan dalam dekompresi GZIP. Mungkin lebih cepat untuk mengekstrak semua file yang di-gzip secara paralel menggunakan xargs dan kemudian memuat data yang sudah di-unzip. Di bawah ini adalah deskripsi tentang apa yang dilaporkan selama proses impor CSV.

$ 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/O     R/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

Saya akan mengosongkan ruang di drive NVMe dengan menghapus file CSV asli sebelum melanjutkan.

$ sudo rm -fr /ch/csv

Konversikan ke Bentuk Kolom

Mesin Log ClickHouse akan menyimpan data dalam format berorientasi baris. Untuk menanyakan data lebih cepat, saya mengonversinya ke format kolom menggunakan mesin MergeTree.

$ clickhouse-client --host=0.0.0.0

Berikut ini selesai dalam 34 menit dan 50 detik. Setelah operasi ini, ukuran direktori data adalah 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;

Ini adalah tampilan sekilas selama pengoperasian:

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/O     R/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)

Pada pengujian terakhir, beberapa kolom dikonversi dan dihitung ulang. Saya menemukan bahwa beberapa fungsi ini tidak lagi berfungsi seperti yang diharapkan pada kumpulan data ini. Untuk mengatasi masalah ini, saya menghapus fungsi yang tidak sesuai dan memuat data tanpa mengonversi ke tipe yang lebih terperinci.

Distribusi data di seluruh cluster

Saya akan mendistribusikan data ke ketiga node cluster. Untuk memulai, di bawah ini saya akan membuat tabel pada ketiga mesin tersebut.

$ 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);

Kemudian saya akan memastikan bahwa server pertama dapat melihat ketiga node di cluster.

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:

Kemudian saya akan mendefinisikan tabel baru di server pertama yang didasarkan pada skema trips_mergetree_third dan menggunakan mesin Terdistribusi.

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

Saya kemudian akan menyalin data dari tabel berbasis MergeTree ke ketiga server. Berikut ini selesai dalam 34 menit dan 44 detik.

INSERT INTO trips_mergetree_x3
    SELECT * FROM trips_mergetree;

Setelah operasi di atas, saya memberi ClickHouse waktu 15 menit untuk menjauh dari tanda tingkat penyimpanan maksimum. Direktori data masing-masing berukuran 264 GB, 34 GB, dan 33 GB di masing-masing dari tiga server.

Evaluasi kinerja cluster ClickHouse

Apa yang saya lihat selanjutnya adalah waktu tercepat yang pernah saya lihat menjalankan setiap kueri pada tabel beberapa kali trips_mergetree_x3.

$ clickhouse-client --host=0.0.0.0

Berikut ini selesai dalam 2.449 detik.

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

Berikut ini selesai dalam 0.691 detik.

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

Berikut ini selesai dalam 0 detik.

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

Berikut ini selesai dalam 0.983 detik.

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;

Sebagai perbandingan, saya menjalankan kueri yang sama pada tabel berbasis MergeTree yang hanya berada di server pertama.

Evaluasi kinerja satu node ClickHouse

Apa yang saya lihat selanjutnya adalah waktu tercepat yang pernah saya lihat menjalankan setiap kueri pada tabel beberapa kali trips_mergetree_x3.

Berikut ini selesai dalam 0.241 detik.

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

Berikut ini selesai dalam 0.826 detik.

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

Berikut ini selesai dalam 1.209 detik.

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

Berikut ini selesai dalam 1.781 detik.

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;

Refleksi hasil

Ini adalah pertama kalinya database berbasis CPU gratis mampu mengungguli database berbasis GPU dalam pengujian saya. Basis data berbasis GPU tersebut telah melalui dua revisi sejak saat itu, namun kinerja yang diberikan ClickHouse pada satu node tetap sangat mengesankan.

Pada saat yang sama, ketika menjalankan Kueri 1 pada mesin terdistribusi, biaya overhead jauh lebih tinggi. Saya harap saya melewatkan sesuatu dalam penelitian saya untuk posting ini karena akan menyenangkan jika waktu kueri berkurang saat saya menambahkan lebih banyak node ke cluster. Namun, hebatnya ketika menjalankan kueri lain, kinerjanya meningkat sekitar 2 kali lipat.

Akan sangat menyenangkan melihat ClickHouse berkembang menjadi mampu memisahkan penyimpanan dan komputasi sehingga dapat diskalakan secara mandiri. Dukungan HDFS, yang ditambahkan tahun lalu, bisa menjadi langkah menuju hal ini. Dalam hal komputasi, jika satu query dapat dipercepat dengan menambahkan lebih banyak node ke cluster, maka masa depan perangkat lunak ini sangat cerah.

Terima kasih telah meluangkan waktu untuk membaca postingan ini. Saya menawarkan layanan konsultasi, arsitektur, dan pengembangan praktik kepada klien di Amerika Utara dan Eropa. Jika Anda ingin mendiskusikan bagaimana saran saya dapat membantu bisnis Anda, silakan hubungi saya melalui LinkedIn.

Sumber: www.habr.com

Tambah komentar