天天看點

在5000億資料中大海撈針,需要怎樣的硬體做支撐?ScyllaDB的測試方案ClickHouse的黑科技

最近看到一篇由Alexander Zaitsev撰寫的,關于ClickHouse性能對比的文章(文末會有報告的原文位址),覺得很有意思,是以拿來與大家分享一下。它有趣的地方在于,這是一篇針對性能對标的,性能對标測評。這算不算螳螂捕蟬,黃雀在後呢?

這篇文章的對标場景,來自于ScyllaDB的一篇測評報告,而在這篇報告中,ScyllaDB曆數了從2001年至今,NoSql資料庫性能達到的幾個關鍵裡程碑。而如今他們宣稱,ScyllaDB能夠在5000億的資料量,以 10億行/每秒 的性能處理資料。

ScyllaDB的測試方案

在ScyllaDB的測試方案中,他們模拟了物聯網的使用場景:

測試資料

資料來自于家庭安裝的溫度傳感器,這些溫度傳感器每隔 1 分鐘讀數一次。

是以,1百萬個傳感器,1年下來的資料量将會是:

1,000,000 24 60 * 365 = 5256 億

硬體配置

在伺服器硬體方面,他們采用了packet.com的雲服務,使用了83個 n2.xlarge.x86 執行個體作為database節點,以及24個 c2.medium.x86 執行個體作為輔助的worker節點。

這真可謂是超豪華陣容,節點配置分别如下:

database work
類型 n2.xlarge.x86 c2.medium.x86
CPU 28 Physical Cores @ 2.2 GHz 24 Physical Cores @ 2.2 GHz
Memory 384 GB of DDR4 ECC RAM 64 GB of ECC RAM
Storage 3.8TB of NVMe Flash 960 GB of SSD
Network 4 × 10GBPS 2 × 10GBPS

測試目标

解答這麼幾個問題:

  1. 從時間跨度為3個月的資料中,分别找到溫度最高和最低的那一天,以及這些讀數來自于哪個傳感器;
  2. 從整年的資料中,分别找到溫度最高和最低的那一天,以及這些讀數來自于哪個傳感器;
  3. 在測試資料中,事先埋入了一些壞的測點,在查詢中排除這些壞的測點(像不像大海撈針)。

ClickHouse的黑科技

Alexander在看到這篇文章之後,覺得它們的測試方案太不經濟了,如果使用ClickHouse的黑魔法,能夠在達到同樣業務需求的背景下,擁有更好的成本效益。一不做二不休,Alexander決定使用一台NUC迷你主機作為ClickHouse的測試硬體。

喪心病狂的硬體對比如下:

ClickHouse ScyllaDB
模式 單節點 叢集
伺服器 1 台 Intel NUC 83台 n2.xlarge.x86 database節點, 24台 c2.medium.x86 worker 節點
4 cores (Intel i7-6770HQ) 2900 cores = 83 x 28 cores (Intel Xeon Gold 5120) + 24 x 24 cores (AMD EPYC 7401p)
32 GB 33408 GB = 83 x 384 GB + 24 x 64 GB
1 TB NVMe SSD 338 TB = 83 x 3.8TB NVMe SSD + 24 x 960GB SSD

在ClickHouse的對比方案中,它與對手的配置差距總是如此之大。

然而,即便在記憶體相差1000倍的情況下,ClickHouse仍然比對手擁有10~100倍的性能。

# 耳聽為虛眼見為實

ClickHouse真的有這麼誇張的性能嗎? 光道聽途說可不行, 咱必須得親自試試,可是我身邊也沒迷你主機啊,隻能拿筆記本 + 虛拟機湊活

虛拟機系統Centos 7, 配置4 cores, 32G:

uname -a    
Linux ch6.nauu.com 3.10.0-1062.el7.x86_64 #1 SMP Wed Aug 7 18:08:02 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
[root@ch6 ~]# 
[root@ch6 ~]# free -g
              total        used        free      shared  buff/cache   available
Mem:             31           0          30           0           0          30
Swap:             1           0           1
[root@ch6 ~]# grep 'core id' /proc/cpuinfo | sort -u | wc -l
4           

ClickHouse版本19.17.4

按照Alexander的例子,首先需要建立一張儲存傳感器資料的測試表:

CREATE TABLE sensors_data (
   sensor_id Int32 Codec(DoubleDelta, LZ4),
   time DateTime Codec(DoubleDelta, LZ4),
   date ALIAS toDate(time),
   temperature Decimal(5,2) Codec(T64, LZ4)
) Engine = MergeTree
PARTITION BY toYYYYMM(time)
ORDER BY (sensor_id, time);
           

在這張資料表的定義中,可謂是做到了極緻的優化。包括:

  • 針對每一個列字段,都單獨聲明了它的encode編碼算法和compresss壓縮算法,這是ClickHouse的一個新特性。簡而言之,如果是時間序列的資料,推薦使用DoubleDelta和LZ4的組合;而在資料模式不明确的情況下,可以使用T64和LZ4的組合。關于算法的這一塊的介紹,以後有時間可以專門寫一篇說明;
  • date類型使用了 ALIAS 計算字段,降低了存儲開銷;
  • 分區Key和主鍵Key,很好的比對了業務的查詢條件。如此一來,在後續的查詢中,就能夠充分利用MergeTree的分區索引和一級索引。

有了資料表之後,就可以開始模拟測試資料了,Alexander使用了numbers_mt函數,模拟了5256億溫度資料:

INSERT INTO sensors_data (sensor_id, time, temperature) \
WITH \
 toDateTime(toDate('2019-01-01')) as start_time,  \
 1000000 as num_sensors, \
 365 as num_days, \
 24*60 as num_minutes, \
 num_days * num_minutes as total_minutes \
SELECT \
 intDiv(number, num_minutes) % num_sensors as sensor_id,  \
 start_time + (intDiv(number, num_minutes*num_sensors) as day)*24*60*60 + (number % num_minutes as minute)*60 time,  \
 60 + 20*sin(cityHash64(sensor_id)) \
 + 15*sin(2*pi()/num_days*day)  \
 + 10*sin(2*pi()/num_minutes*minute)*(1 + rand(1)%100/2000)  \
 + if(sensor_id = 473869 and  \
      time between '2019-08-27 13:00:00' and '2019-08-27 13:05:00', -50 + rand(2)%100, 0)  \
 as temperature \
FROM numbers_mt(525600000000) \
SETTINGS max_block_size=1048576;
           

接下來幹什麼呢?接下來可以去睡覺了。由于是單線程寫入,我粗略計算了一下,大概隻要40~50個小時,資料就能全部寫進去了 !!!

在這段等待的時間,我們繼續往下分析。當資料寫完之後,這張 sensors_data 資料表并不能直接作為查詢表使用,還需要進一步為它建立物化視圖:

CREATE MATERIALIZED VIEW sensors_data_daily( \
  sensor_id Int32 Codec(DoubleDelta, LZ4), \
  date Datetime Codec(DoubleDelta, LZ4), \
  temp_min SimpleAggregateFunction(min, Decimal(5,2)), \
  temp_max SimpleAggregateFunction(max, Decimal(5,2)) \
) Engine = AggregatingMergeTree \
PARTITION BY toYYYYMM(date) \
ORDER BY (sensor_id, date) \
POPULATE \
AS  \
SELECT sensor_id, date,  \
   min(temperature) as temp_min, \
   max(temperature) as temp_max \
FROM sensors_data \
GROUP BY sensor_id, date;           

物化視圖會自動同步sensors_data的資料。

由于使用了AggregatingMergeTree表引擎,資料在AggregatingMergeTree合并分區的過程中,會以分區目錄為機關,按照 sensor_id和date預先聚合。

是以,這裡其實是玩了一個ClickHouse的常用技巧,那就是利用物化視圖進行了預聚合的優化。使用物化視圖和MergeTree組合使用,是ClickHouse的殺手锏之一。

在這個例子中,有點類似資料立方體的意思,通過預聚合, 将聚合結果預先存在表内,在之後查詢的過程中,可以從結果直接傳回。與此同時,預先聚合還能有效的減少資料行,在這個例子中,最終能将視圖内的資料行減少1400倍之多。

正如ScyllaDB的文章中所說,他們的測試并不是一場 apples to apples 的比較。同樣的,我想Alexander拿ClickHouse做的這場比較,也不是針尖對麥芒的。它們兩者之間有着太多的不同,它們使用了不同的資料模型、不同的架構等等。

但是通過這個案例的對比,大家可以認識到ClickHouse确實是經濟和性能的完美平衡。如果你的業務也有類似的場景,使用ClickHouse将會是一種不錯的選擇。

由于我的資料還沒寫完。。。 關于論證的結果,隻能留在下一篇了。

繼續閱讀