1.1 миллиард поездок на такси: 108-ядерный кластер ClickHouse

от автора

Перевод статьи подготовлен специально для студентов курса «Data Engineer».

___________________

ClickHouse — это колоночная база данных с открытым исходным кодом. Это великолепная среда, где сотни аналитиков могут быстро запрашивать развернутые данные, даже когда вводятся десятки миллиардов новых записей в день. Расходы на инфраструктуру для поддержки такой системы могут достигать 100 тыс. долларов США в год, и потенциально вдвое меньше, в зависимости от использования. В какой-то момент инсталяция ClickHouse от Яндекс Метрики содержала 10 триллионов записей. Помимо Яндекса, ClickHouse также снискала успех у Bloomberg и Cloudflare.

Два года назад я провел сравнительный анализ баз данных с использованием одной машины, и она стала самым быстрым бесплатным программным обеспечением для баз данных, которое я когда-либо видел. С тех пор разработчики не переставали добавлять фичи, включая поддержку Kafka, HDFS и ZStandard сжатия. В прошлом году они добавили поддержку каскадирования методов сжатия, и дельта-от-дельты кодирование стало возможным. При сжатии данных временных рядов gauge-значения могут хорошо сжиматься с помощью дельта-кодирования, но для счетчиков (counter) будет лучше использовать дельта-от-дельты-кодирование. Хорошее сжатие стало ключом к производительности ClickHouse.

ClickHouse состоит из 170 тысяч строк C++ кода, за исключением сторонних библиотек, и является одной из наименьших кодовых баз для распределенных баз данных. Для сравнения, SQLite не поддерживает распределение и состоит из 235 тысяч строк кода на языке С. На момент написания этой статьи свой вклад в ClickHouse внесли 207 инженеров, и интенсивность коммитов в последнее время увеличивается.

В марте 2017 года ClickHouse начал вести журнал изменений в качестве простого способа отслеживать разработку. Они также разбили монолитный файл документации на иерархию файлов на основе Markdown. Проблемы и фичи отслеживаются через GitHub, и в целом это программное обеспечение стало намного более доступным в последние несколько лет.

В этой статье я собираюсь взглянуть на производительность кластера ClickHouse на AWS EC2 с использованием 36-ядерных процессоров и NVMe-накопителя.

АПДЕЙТ: Через неделю после первоначальной публикации этого поста я повторно запустил тест с улучшенной конфигурацией и достиг гораздо лучших результатов. Этот пост был обновлен, чтобы отразить эти изменения.

Запуск кластера AWS EC2

Я буду использовать три экземпляра c5d.9xlarge EC2 для этого поста. Каждый из них содержит 36 виртуальных ЦП, 72 ГБ ОЗУ, 900 ГБ накопителя NVMe SSD и поддерживает 10-гигабитную сеть. Они стоят $1,962/час каждый в регионе eu-west-1 при запуске по требованию. Я буду использовать Ubuntu Server 16.04 LTS в качестве операционной системы.

Фаервол настроен так, что каждая машина может связываться друг с другом без ограничений, и только мой IPv4-адрес занесен в белый список SSH в кластере.

NVMe-накопитель в состоянии рабочей готовности

Для работы ClickHouse я создам в NVMe-накопителе файловую систему в формате EXT4 на каждом из серверов.

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

После того как все настроено, вы можете увидеть точку монтирования и 783 ГБ пространства, доступного в каждой из систем.

$ 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

Набор данных, который я буду использовать в этом тесте, представляет собой дамп данных, который я сформировал из 1.1 миллиарда поездок на такси, произведенных в Нью-Йорке за шесть лет. В блоге Миллиард поездок на такси в Redshift подробно рассказывается о том, как я собрал этот набор данных. Они хранятся в AWS S3, поэтому я настрою интерфейс командной строки AWS с помощью моего доступа и секретных ключей.

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

Я установлю ограничение количества одновременных запросов клиента на 100, чтобы файлы загружались быстрее, чем при стандартных настройках.

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

Я скачаю набор данных поездок на такси с AWS S3 и сохраню его на диске NVMe на первом сервере. Этот набор данных составляет ~ 104 ГБ в GZIP-сжатом CSV-формате.

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

Установка ClickHouse

Я установлю дистрибутив OpenJDK для Java 8, так как он необходим для запуска Apache ZooKeeper, необходимого для распределенной установки ClickHouse на всех трех машинах.

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

Затем я устанавливаю переменную среды JAVA_HOME.

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

Затем я буду использовать систему управление пакетами в Ubuntu для установки ClickHouse 18.16.1, glances и ZooKeeper на все три машины.

$ 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

Я создам каталог для ClickHouse, а также совершу некоторые переопределения конфигурации на всех трех серверах.

$ 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

Это переопределения конфигурации, которые я буду использовать.

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

Затем я запущу ZooKeeper и сервер ClickHouse на всех трех машинах.

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

Загрузка данных в ClickHouse

На первом сервере я создам таблицу поездок (trips), в которой будет храниться набор данных поездок в такси с использованием движка 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;

Затем я распаковываю и загружаю каждый из CSV-файлов в таблицу поездок (trips). Следующее выполнено за 55 минут и 10 секунд. После этой операции размер каталога данных составил 134 ГБ.

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

Скорость импорта составляла 155 МБ несжатого CSV-контента в секунду. Я подозреваю, что это было связано с узким местом в GZIP-декомпрессии. Возможно, быстрее было распаковать все файлы gzip параллельно, используя xargs, а затем загрузить распакованные данные. Ниже приведено описание того, что сообщалось в процессе импорта 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

Я освобожу место на NVMe-приводе, удалив исходные CSV-файлы, прежде чем продолжить.

$ sudo rm -fr /ch/csv

Преобразование в колоночную форму

Движок Log ClickHouse будет хранить данные в строко-ориентированном формате. Чтобы быстрее запрашивать данные, я конвертирую их в колоночный формат с помощью движка MergeTree.

$ clickhouse-client --host=0.0.0.0

Следующее выполнено за 34 минуты и 50 секунд. После этой операции размер каталога данных составил 237 ГБ.

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;

Вот как выглядел glance-вывод во время операции:

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)

В последнем тесте несколько столбцов были преобразованы и пересчитаны. Я обнаружил, что некоторые из этих функций больше не работают должным образом в этом наборе данных. Для решения этой проблемы я удалил неподходящие функции и загрузил данные без преобразования в более детализированные типы.

Распределение данных по кластеру

Я буду распределять данные по всем трем узлам кластера. Для начала ниже я создам таблицу на всех трех машинах.

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

Затем я позабочусь о том, чтобы первый сервер мог видеть все три узла в кластере.

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:

Затем я определю новую таблицу на первом сервере, которая основана на схеме trips_mergetree_third и использует движок Distributed.

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

Затем я скопирую данные из таблицы на основе MergeTree на все три сервера. Следующее выполнено за 34 минуты и 44 секунды.

INSERT INTO trips_mergetree_x3     SELECT * FROM trips_mergetree;

После приведенной выше операции я дал ClickHouse 15 минут, чтобы отойти от отметки максимального уровня хранилища. Каталоги данных в конечном итоге составляли 264 ГБ, 34 ГБ и 33 ГБ соответственно на каждом из трех серверов.

Оценка производительности кластера ClickHouse

То, что я увидел дальше, было самым быстрым временем, которое я видел при многократном выполнении каждого запроса в таблице trips_mergetree_x3.

$ clickhouse-client --host=0.0.0.0

Следующее выполнено за 2.449 секунды.

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

Следующее выполнено за 0.691 секунды.

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

Следующее выполнено за 0.,582 секунды.

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

Следующее выполнено за 0.983 секунды.

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;

Для сравнения я выполнил те же запросы в таблице на основе MergeTree, которая находится исключительно на первом сервере.

Оценка производительности одного узла ClickHouse

То, что я увидел дальше, было самым быстрым временем, которое я видел при многократном выполнении каждого запроса в таблице trips_mergetree_x3.

Следующее выполнено за 0.241 секунды.

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

Следующее выполнено за 0.826 секунды.

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

Следующее выполнено за 1.209 секунды.

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

Следующее выполнено за 1.781 секунды.

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;

Размышления о результатах

Это первый раз, когда бесплатная база данных на базе процессора смогла превзойти базу данных на основе GPU в моих тестах. Та база данных на основе GPU с тех пор подверглась двум ревизиям, но, тем не менее, производительность, которую ClickHouse показал на одном узле, очень впечатляет.

При этом при выполнении Query 1 на распределенном движке накладные расходы оказываются на порядок выше. Я надеюсь, что что-то пропустил в своем исследовании для этого поста, потому что было бы хорошо увидеть, как время запросов снижается, когда я добавляю больше узлов в кластер. Однако это замечательно, что при выполнении других запросов производительность выросла примерно в 2 раза.

Было бы неплохо, если бы ClickHouse развивался в направлении того, чтобы можно было отделить хранилище и вычисления, чтобы они могли масштабироваться независимо. Поддержка HDFS, которая была добавлена в прошлом году, может стать шагом к этому. Что касается вычислений, если один запрос может быть ускорен при добавлении большего количества узлов в кластер, то будущее этого программного обеспечения будет очень безоблачным.

Спасибо, что нашли время, чтобы прочитать этот пост. Я предлагаю консалтинг, архитектуру и услуги по практическому развитию для клиентов в Северной Америке и Европе. Если вы хотите обсудить, как мои предложения могут помочь вашему бизнесу, свяжитесь со мной через LinkedIn.


ссылка на оригинал статьи https://habr.com/ru/company/otus/blog/463665/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *