之前,因为 Apache IoTDB 多项性能表现位居 benchANT 时序数据库排行榜(Time Series: DevOps)性能排行第一名,我们进行了基于 benchANT 榜单的背景介绍和基于它测试基准的环境复现。还没有看的友友们可以点此查看哦!

下面我们将继续介绍我们复现的写入、查询具体测试步骤,并分析对比 Apache IoTDB 及其它时序数据库的性能表现。

4

命令集脚本

本章节介绍 benchANT 测试流程使用的命令集脚本。

用户首先需要在AWS创建EC2实例来部署测试客户端与数据库服务端。客户端对应的EC2规格代码固定为c5.4xlarge,服务端根据测试负载不同对应两类规格代码m5.largem5.xlarge。EC2实例操作系统选择ubuntu,存储类型选择GP2,存储容量为100GB。

创建完EC2实例后,用户需要在客户端部署tsbs,在服务端部署IoTDB Server(采用默认的 1ConfigNode + 1DataNode模式部署)。客户端安装好Golang编译环境后,通过链接https://github.com/benchANT/tsbs将代码下载至本地,在代码目录执行make命令即可一键生成可执行程序,以下4个步骤涉及的“数据生成”、“数据导入”、“生成查询”及“执行查询”程序均位于bin目录下。

本章节假设 IoTDB Server 部署在m5.xlarge实例上,部署的机器IP 为 172.31.8.255。

4.1

数据生成

nohup bin/tsbs_generate_data --use-case="devops" --seed=123 --scale=1000 \
  --timestamp-start="2022-07-25T00:00:00Z" \
  --timestamp-end="2022-07-28T00:00:00Z" \
  --log-interval="10s" --format="iotdb" \
  > iotdb-data-1000hosts-3days &

其中参数的含义如下:

  • use-case:测试场景,有"devops"与"iot"两种。benchANT 测试使用的是"devops"。该场景模拟了服务器运行时的监控数据。

  • seed:数据生成的随机数种子。

  • scale:devops 场景中 host/ 服务器的数量,等同于 IoTDB 里设备的数量。

  • timestamp-start:生成数据集的开始时间。

  • timestamp-end:生成数据集的结束时间。

  • log-interval:每条数据的时间间隔。

  • format:指定数据库。

生成的数据集格式如下所示,其中 0 开头的对应于 IoTDB 中的时间序列创建语句,1 开头的表示数据插入语句。

0,cpu,host_3,tag,'hostname'='host_3','region'='us-east-1','datacenter'='us-east-1a','rack'='7','os'='Ubuntu16.04LTS','arch'='x64','team'='NYC','service'='19','service_version'='0','service_environment'='test'
1,cpu,host_3,1677628800000,55,20,15,61,30,19,20,5,16,65

4.2

数据导入

nohup cat iotdb-data-1000hosts-3days | bin/tsbs_load_iotdb \
--host="172.31.8.255" --port="6667" --user="root" --password="root" --timeout=1000 \
--workers=100 --batch-size=1000 > output.log 2>&1 &

其中参数的含义如下:

  • host:IoTDB server 部署的地址,本文假设 IoTDB 部署的地址为"172.31.8.255"。

  • port:IoTDB server 部署的端口,默认为 6667。

  • user:IoTDB 连接用户名,默认为 root。

  • password:IoTDB 连接密码,默认为 root。

  • timeout:IoTDB 执行请求的超时时间。

  • workers:并发客户端数量。

  • batch-size:批处理大小,benchANT 客户端每次转发的数据行数。

该命令执行结束之后,会在output.log文件保存写入测试的结果,包含导入的数据总量、导入耗时、写入吞吐等指标。

4.3

生成查询

bin/tsbs_generate_queries --use-case="devops" --seed=123 --scale=1000 \
  --timestamp-start="2022-07-25T00:00:00Z" \
  --timestamp-end="2022-07-28T00:00:00Z" \
  --queries=100000 --query-type="single-groupby-1-1-1" --format="iotdb" \
  > iotdb-queries.txt

其中参数的含义如下:

  • timestamp-start:查询数据集的开始时间。

  • timestamp-end:查询数据集的结束时间。

  • use-case:测试场景,与写入数据生成时使用的参数保持一致。

  • seed:数据生成的随机数种子。与写入数据生成时使用的参数保持一致。

  • scale:devops 场景中 host/ 服务器的数量,等同于 IoTDB 里设备的数量,与写入数据生成时使用的参数保持一致。

  • queries:生成的查询测试语句的数量。

  • query-type:查询类型。benchANT 测试使用了查询类型"single-groupby-1-1-1",即查询一个设备、一个测点在 1 小时内按分钟分段聚合的结果。生成的查询语句示例:

SELECT MAX_VALUE(usage_user) FROM root.cpu.host_1 GORUP BY ([2022-07-25 00:00:00, 2022-07-25 01:00:00), 1h)

执行完该条命令后,总共会生成十万条查询语句,每个查询语句会从Metric "CPU"下的1000个设备里随机选择1个设备、从"2022-07-25T00:00:00Z"至"2022-07-28T00:00:00Z"的时间区间内随机选择1个小时作为查询条件。

4.4

执行查询

cat iotdb-queries.txt | bin/tsbs_run_queries_iotdb \
--host="172.31.8.255" --port="6667" --user="root" --password="root" \
--workers=100 --print-responses=false --use-groupby=true

其中参数的含义如下:

  • host:IoTDB server 部署的地址,本文假设 IoTDB 部署的地址为"172.31.8.255"。

  • port:IoTDB server 部署的端口,默认为 6667。

  • user:IoTDB 连接用户名,默认为 root。

  • password:IoTDB 连接密码,默认为 root。

  • workers:并发客户端数量。

  • print-responses:是否打印查询的结果。

  • use-groupby:使用 IoTDB GroupBy RPC 接口。

该命令执行结束之后,会打印出查询测试的结果,包含查询延迟、查询吞吐等指标。

为了使得 JIT 可以更好的进行代码编译预热,上述测试语句可以重复执行 3 次,每次执行间隔 30s。

5

性能对比

上一章节介绍了测试的命令集脚本,在本章节中会介绍 IoTDB 的测试结果以及达到该性能所采用的建模方式及调优参数。

5.1

IoTDB 建模

在测试中,IoTDB 的建模如下图所示,监控的 9 个大项 metric 作为 9 个 db,每个 db 下均有 1000 个设备(代表 1000 台服务器),每个 db 下的设备采集的测点保持一致,如 cpu metric 下一共记录了 10 个测点,分别为:usage_user、usage_system、usage_idle、usage_nice、usage_iowait、usage_irq、usage_softirq、usage_steal、usage_guest 和 usage_guest_nice,这 10 项测量值的数据类型均为 INT,记录了用户侧 CPU 使用率、系统侧 CPU 使用率等;mem metric 下一共记录了 9 个测点,分别为:total、available、used、free、cached、buffered、used_percent、available_percent 及 buffered_percent,这 9 项测量值的数据类型为 INT 或 DOUBLE,记录了内存总量、内存可用量、内存空闲量等。9 个大项监控指标累计记录了 101 项测量值。

除了测量值外,每个设备也会记录其专属的 tags 信息(标签值),标签值是设备的描述,其不随时间而进行改变,在 benchANT 测试场景中设备的 tags 信息记录了 region、datacenter、rack、os、arch、team、service、service_version 及 service_environment 字段,IoTDB 将 tags 数据当作一个测点存储于设备之下,并在该测点上添加 tags 索引。

在该建模中,每个设备均为对齐设备,即该设备下所有测点的时间戳都是“对齐”的,采用对齐设备,可以在一定程度上提升写入性能,降低存储空间占用。

另外我们可以发现,对于每一个 db,该 db 下的所有设备挂载的测点都是相同的,实际上这种结构也可使用 IoTDB 中的“模板”进行优化,以 cpu metric 为例,在 IoTDB 中创建一个 cpu 模板 cpu_template:

create schema template cpu_template (
usage_user INT32, usage_system INT32, usage_idle INT32, usage_nice INT32, usage_iowait INT32, usage_irq INT32, usage_softirq INT32, usage_steal INT32, usage_guest INT32, usage_guest_nice INT32);
set schema template cpu_tempalte to root.cpu;

然后将该模板挂载至 root.cpu 层级并激活即可,如此 root.cpu 下的设备都会包含 cpu 模板中包含的测点。通过使用模板,可以降低数据库的元数据空间占用。

98fff53689d1910b58b0193a87dfb880.png

5.2

性能分析

在 benchANT 测试中,IoTDB 提供了两个版本的配置参数:Vanilla 与 Tuned,其中 Vanilla 为默认参数,即使用 IoTDB 默认的配置文件,仅修改了 JAVA 的最大堆内内存;Tuned 为进阶参数,根据机器的配置与测试负载对数据库的参数进行了相应的适配。

下表以 benchANT Small Scaling 环境( 4 核 16GB、单机部署)为例,介绍了 IoTDB 在 Vanilla 版本与 Tuned 版本下设置的参数,通过这些参数的对比,用户也可以了解 IoTDB 常见的调优方向。

378a3d85b46f8e8fa12b95335f4e61e9.png

  • 内存参数:Vanilla 环境仅将 DataNode 的最大堆内内存设置机器内存*0.75,这种设置相对简单。Tuned 环境对 ConfigNode 与 DataNode 使用的内存进行了更加细致的分配。ConfigNode 存储的是集群全局数据,该部分数据通常占用空间较小,所以可以给 ConfigNode 分配较少的内存。DataNode 存储了真实的时间序列元数据与数据,该部分占用空间较大,所以给 DataNode 分配较多的内存。

  • GC 算法:JDK17 使用的默认 GC 算法为 G1,G1 算法以回收效率优先。而在 benchANT 的评测中,Throughput(写入吞吐、查询吞吐等)是一个重要的数据库性能衡量指标,所以可以将 GC 算法调整为更加关注吞吐量的 Parallel GC 算法。

  • 共识协议:benchANT 测试的 xSmall 与 small 场景均为数据库单机部署,而 IoTDB 默认的共识协议 Ratis,IoT 主要适配分布式集群;对于单机实例部署,采用 Simple 共识协议便可满足要求。

  • 合并参数:benchANT 测试中有一项评估指标为“存储空间占用”,而“存储空间占用”会在查询评测结束时进行统计,所以为了达到较低的“存储空间占用”,IoTDB-Tuned 适当加强了合并的力度,可以在更短的时间内完成数据合并。

  • 数据分区参数:IoTDB 在 benchANT 测试的建模中会生成 9 个 database,而 benchANT 使用的测试机器规格相对较小,所以为每个 database 分配一个 data region 便可达到足够的并行度。当机器规格提升时,可以通过调整 default_data_region_group_num_per_database 参数来提升写入及查询的并行度。

  • 其他参数:该部分列出的参数对 IoTDB 的性能影响相对较小。

    • enable_last_cache 用于控制是否开启 last 缓存,由于 benchANT 查询测试中没有最新值查询,所以可以关闭最新值缓存功能。由于 IoTDB 采用了高效的最新值缓存算法,所以该参数的开关对写入性能相对较小。

    • dn_metric_level 是 IoTDB 监控写入的级别,开启该指标主要用于线上问题排查;监控数据的采集会造成 CPU 使用率些微升高,在 benchANT 测试中可关闭该选项。

    • max_number_of_points_in_page 用于控制 TsFile 中 Page 的数据点数,通常数据点数越多、数据的压缩效果越好。同时 Page 里的数据点数也会影响查询的性能,benchANT 的查询测试只会查询 1 小时范围内的点,所以综合考虑压缩率与查询性能后,Tuned 环境将该值设置为合适的点数。

    • wal_async_mode_fsync_delay_in_ms 用于控制 WAL 模块调用 fsync 的频率,以保证数据落盘的可靠性。IoTDB-WAL 默认采用 fsync 模式,fsync_delay 等于 1 秒。通常 fsync 的频率越高,消耗的 IO 资源越多,对写入性能造成的影响越大。由于 IoTDB 采用了批量写等优化,大幅降低了 fsync 的频率对写入性能的影响,Tuned 环境将 fsync_delay 设置成 3 秒即可满足需求。

下图所示为 benchANT 在时序场景下的测试榜单,可以看到 IoTDB 在 small Scaling 环境与 xSmall Scaling 环境下的读、写、存储性能均排在首位,且大幅领先其他数据库产品。下文将基于榜单详细分析 IoTDB 与其他时序数据库的性能差异。

写入吞吐(WRITE THROUGHPUT):表示单位时间内处理的写入数据点数量,该数值越高表明数据库写入性能越高。在 small Scaling 环境下,IoTDB 的写入吞吐为 3,636,312 ops,是 InfluxDB 的 6.9 倍、TimescaleDB 的 2.3 倍、QuestDB 的 1.4 倍;在 xSmall Scaling 环境下,IoTDB 的写入吞吐为 1,426,490 ops,是 InfluxDB 的 5.4 倍、TimescaleDB 的 1.1 倍、QuestDB 的 2.8 倍。可以看到,无论是小规格机器或大规格机器,IoTDB 都能很好的压榨机器性能,表现出高效的写入效率。并且随着机器规格的提升,IoTDB 写入性能的提升也更加明显,领先其他数据库的比例也更多。

查询延迟(READ LATENCY):表示单个查询的响应时间,该数值越低表明数据库处理单个查询的速度越快。在 small Scaling 环境下,查询延迟为 2ms,查询速度是 InfluxDB 的 23 倍、TimescaleDB 的 97 倍、QuestDB 的 57 倍;在 xSmall Scaling 环境下,查询延迟为 1ms,查询速度是 InfluxDB 的 47 倍、TimescaleDB 的 430 倍、QuestDB 的 82 倍。通过测试结果可以看出,IoTDB 的查询性能领先其他数据库达十倍甚至百倍,在保持高写入性能的前提下,通过合理的文件结构设计与文件合并机制,借助于 IoTDB 强大的查询引擎及丰富的查询接口设计,IoTDB 的查询性能也达到了极致。

存储占用(STORAGE CONSUMPTION):表示存储空间占用,记录测试运行过程中的磁盘平均使用量。在 small Scaling 环境与 xSmall Scaling 环境中,IoTDB 的存储空间使用量均为 2GB,排名位于榜首,这体现了 IoTDB 的“极致压缩”能力。IoTDB 提供了丰富的编码与压缩算法,能够极好的适应各种数据类型与数据分布。在 benchANT 测试中,INT 类型使用 TS_2DIFF 编码、DOUBLE 类型使用了 GORILLA 编码,压缩方式采用了 LZ4,在保持了高压缩比的同时还能保证高写入查询性能,最终的测试结果验证了 IoTDB 的“高效读写、极致压缩”。

成本收益(OPERATIONS PER COST):,数值越高越好,因为 IoTDB 在单位成本内可执行的写入请求及查询请求是最多的,所以 IoTDB 的成本收益排名第一。

small Scaling 环境下的测试榜单:

90994afaea3a7b9d42273f2529b60172.png

xSmall Scaling 环境下的测试榜单:

2ad02616e0650c99be78e3679bf6c889.png

6

总结

从测试结果可以看到,无论是在小规格机器或大规格机器上,IoTDB 都能很好的利用机器性能,表现出高效的写入效率。并且随着机器规格的提升,IoTDB 写入性能的提升也更加明显,领先其他数据库的比例也更多

在保持高写入性能的前提下,通过合理的文件结构设计与文件合并机制,借助于 IoTDB 强大的查询引擎及丰富的查询接口设计,IoTDB 的查询性能领先其他数据库达十倍甚至百倍

IoTDB 提供了丰富的编码与压缩算法,能够极好的适应各种数据类型与数据分布。在 benchANT 测试中,INT 类型使用 TS_2DIFF 编码、DOUBLE 类型使用了 GORILLA 编码,压缩方式采用了 LZ4,在保持了高压缩比的同时还能保证高写入查询性能,最终的测试结果验证了 IoTDB 的“高效读写、极致压缩”

benchANT对时序数据库测试的结果,证明了 Apache IoTDB 强大的性能和与较其他数据库系统的巨大优势

更多内容推荐:

• 了解如何使用 IoTDB 企业版

09e1225c7d5488e316b7f01b6155b2ba.gif

2385b35c8ddb964034de069f18408682.png

b68f19cb3db41ae69b32bef11b9e5cbb.png

07d45efe072317b32a1e2a41a7ab56d3.png

9801770045fe2546ef96c602ec788fd8.gif

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐