一、背景
在物联网、车联网等时序数据场景中,数据的高速写入能力至关重要,会对产品方案的可用性、可靠性和扩展性产生影响。
以物联网为例,当面临千万甚至上亿设备、平均每个设备采集几十个到几百个指标时,每秒生成的数据将达到数十亿至数百亿。能否及时可靠的插入这种量级的数据,是评价一个时序数据库的核心要素和第一需求。
因此,对于时序数据库的性能进行测试也就尤为重要,TSBS 作为一款对时序数据库批量加载性能和查询执行性能的开源测试工具,得到了越来越多的应用。
二、TSBS 介绍
Time Series Benchmark Suite (TSBS) 是一个使用 go 语言编写的,用于生成时序数据集的基准测试工具,可以对各种时序数据库的读写性能进行基准测试。TSBS 具有可扩展性, 可以对各种时序数据场景(例如 devops,IoT 等)进行批量写入性能和查询执行性能基准测试。
目前 TSBS 支持 IOT 及 Devops 两种场景:
- IoT 场景:模拟物联网环境中的数据负载,这个用例模拟来自一个虚构的卡车公司的一组卡车的数据流,包括来自每辆卡车的诊断数据和指标,并引入了相关的环境因素,例如 out-of-order 数据和批量摄取(对于离线一段时间的卡车)。它还跟踪卡车元数据,并使用它将度量和诊断作为查询集的一部分联系在一起。
- Devops 场景:"开发操作"用例,有两种形式。完整形式用于生成、插入和测量 9 个"系统"中的数据,这些数据可以在真实的devops场景(e.g.、CPU、内存、磁盘等)中进行监控。这 9 个系统一起在每个读取间隔生成 100 个度量。另一种形式只关注CPU指标,以实现更简单、更精简的用例。这个用例每次读取生成 10 个 CPU 指标。除了度量读数之外,还为数据集中的每个主机生成"标记"(包括主机的位置、操作系统等)。
目前支持的数据库:
- Akumulie
- Cassandrae
- ClickHousee
- CrateDBe
- InfluxDB
- MongoDB
- SiriDBe
- TimescaleDB
- VictoriaMetricse
未支持 TSBS 的时序数据库,可自行适配数据库类型后开展性能测试工作。
三、TSBS 测试工具
1. TSBS 测试工具安装
(1)使用 go get 对 TSBC 及其相关应用进行下载
shell
$ go get github.com/timescale/tsbs
$ cd /root/go/src/github.com/timescale/tsbs/cmd
$ go get ./...
(2)切换到 cmd 下使用 go install 进行部分应用的安装
shell
#Install desired binaries. At a minimum this includes tsbs_generate_data,
#tsbs_generate_queries, one tsbs_load_* binary, and one tsbs_run_queries_* binary:
$ cd $GOPATH/src/github.com/timescale/tsbs/cmd
$ cd tsbs_generate_data && go install
$ cd ../tsbs_generate_queries && go install
$ cd ../tsbs_load_timescaledb && go install
$ cd ../tsbs_run_queries_timescaledb && go install
(3)切换到 cmd 下使用 go install 进行剩下的安装
shell
#Optionally, install all binaries:
$ cd $GOPATH/src/github.com/timescale/tsbs/cmd
$ go install ./...
2. TSBS 测试工具使用
TSBS 基准测试分为 3 个阶段:数据生成和查询语生成、数据写入/插入测试、查询测试。下面 TSBS 测试工具三个阶段的使用以 IOT 场景和 timescaledb 数据库为例进行介绍。
(1)数据生成
通过 TSBS 生成基准测试的数据,将其作为基准测试阶段的输入。需要的变量,如下:
- --use-case:使用场景,包括iot、devops、cpu-only,例如iot;
- --seed:用于确定性生成的 PRNG 种子。例如:123;
- --scale:要生成的卡车/设备数量。例如:50000;
- --timestamp-start:数据中时间戳的开始时间。例如:2016-01-01T00:00:00Z;
- --timestamp-end:数据中时间戳的结束时间。例如:2016-01-01T00:10:00Z;
- --log-interval:每个设备的每次读取之间应该间隔多长时间,以秒为单位。例如:10s;
- --format:需要生成的数据库,例如: timescaledb。
可自行设置变量在自定义目录下生成数据文件,示例:如使用上述变量生成数据集(在自定义目录/tmp/下生成 tsdb-data 数据文件)。
上面示例会生成一个伪 -CSV 文件,用于将数据批量加载到 TimescaleDB 中。每个数据库都有自己的格式,用于存储数据,使其数据库对应的加载器最容易写入数据。
(2)查询生成
需要的变量,如下:
- 与数据生成中的用例、卡车数量、开始时间相同;
- --timestamp-end:数据生成后一秒的结束时间,例如:对于 2016-01-01T00:10:00Z 使用 2016-01-01T00:10:01Z;
- --queries:生成的SQL语句的查询数,例如:1000;
- --query-type:要生成的SQL语句查询类型,例如:" specific-sub-table ";
例如:下列为生成 timescaledb 单类型一组查询的例子,可以通过改变查询类型 --query-type 一项来生成其他查询语句类型(查询类型的完整列表见末尾附录内容):
ini
$ tsbs_generate_queries --use-case="iot" --seed=123 --scale=50000 \
--timestamp-start="2016-01-01T00:00:00Z" \
--timestamp-end="2016-01-01T00:10:01Z" \
--queries=1000 --query-type=" specific-sub-table " --format="timescaledb" \
--use-additional-tags=false | gzip > /tmp/timescaledb-queries- specific-sub-table.gz
( 3)数据插入/写入测试
TSBS 通过获取上一步中生成的数据并将其用作特定于数据库的命令行程序的输入来测量插入/写入性能。tsbs_load 可执行文件可以在任何受支持的数据库中加载数据。可使用预生成的数据文件作为输入。每个加载程序确实共享一些公共标志------例如,batch-size 批处理大小(一起插入的读取数)、worker(并发插入的客户端的数量)、连接详细信息(主机和端口)等。要查找特定数据库的标志,请使用 -help 标志(例如,tsbs_load_timescaledb -help)。
例如:
css
#use insert
$ tsbs_load_timescaledb --postgres="sslmode=disable" --host=172.24.0.2 --port=5432 --pass="inspur123" --user="postgres" --admin-db-name=postgres --workers=1 --in-table-partition-tag=false --field-index-count=0 --do-create-db=true --force-text-format=false --do-abort-on-exist=false --file="/tmp/timescaledb-data" --partitions=1 --use-insert=true --batch-size=8000
#use load
$ tsbs_load_timescaledb --postgres="sslmode=disable" --host=172.24.0.2 --port=5432 --pass="inspur123" --user="postgres" --admin-db-name=postgres --workers=1 --in-table-partition-tag=false --field-index-count=0 --do-create-db=true --force-text-format=false --do-abort-on-exist=false --file="/tmp/timescaledb-data" --partitions=1 --use-insert=false --batch-size=8000
会在 TimescaleDB 中创建一个名为 benchmark 的新数据库,存储数据。在加载完整数据集时除最后两行之外的所有行都包含 CSV 格式的数据,标题中包含列名。这些列名对应于:时间戳、期间每秒的指标、插入总指标、每秒总体指标、期间每秒行数、总行数、每秒总行数。最后两行为插入指标数目(和适用的行),时间和平均写入速率。可以通过更改 --workers 的值以控制同时运行的并行 load 的级别,通过更改 --partitions 的值改变分区数。
(4)查询测试
要测量 TSBS 中的查询执行性能,您首先需要使用上一节加载数据并生成如前所述的查询。加载数据并生成查询后,只需为正在测试的数据库使用相应的 tsbs_run_queries_ 二进制文件,通过更改数据库以及数据库对应自定义目录下生成的查询语句类型来实现各类型的查询性能测试。缺少的条件也可以根据 -help 进行查询。
例如:
对于 timescaledb 数据库查询"specific-sub-table":
ini
$ cat /tmp/timescaledb-queries- specific-sub-table.gz | \
gunzip | bin/tsbs_run_queries_timescaledb --workers=1 \
--hosts=172.24.0.2 --port=5432 --pass=123456 \
--postgres="user=postgres database=benchmark sslmode=disable"
可以通过更改 --workers 的值以控制同时运行的并行查询的级别。
四、实践
1. 测试环境
2. 导入性能测试
测试使用 TSBS 测试工具生成 IoT 场景下卡车运输公司的卡车数据集(约 9.9G),测试:TimescaleDB 在 workes=2 下 partitions 分别为 1、50、100、150 下的导入/查询性能;
workes=1、2、4、8 下 TimescaleDB 的导入/查询性能。
测试结果:
workers=2 下 TimescaleDB 测试不同 partitions,partitions=50 下具有最优导入性能。具体如下图所示:
在 partitions=50 时测试不同 workers 下 TimescaleDB 的导入性能,TimescaleD 导入性能如下所示:
3. 查询性能测试
测试 workers=2,不同 partitions(1, 50, 100, 150)下 TimescaleDB 的查询性能;
不同 workers(1, 2, 4, 8)下 TimescaleDB 的查询性能。
(1)查询语句:
query-specific-sub-table :
sql
SELECT t.driver, r.latitude, r.longitude
FROM tags t
INNER JOIN LATERAL (SELECT latitude, longitude, name FROM readings)
AS r ON r.name = t.name
WHERE t.name IS NOT NULL
AND t.name = GetRandomName()
query-stationary-trucks-avg-velocity:
sql
SELECT t.name, t.driver, avg(r.velocity) as avg_velocity
FROM tags t
INNER JOIN readings r ON r.name = t.name
WHERE time >= Start()
AND time < End()AND t.name IS NOT NULL
AND t.fleet = GetRandomFleet()
GROUP BY 1, 2
(2)测试结果:
query-stationary-trucks-avg-velocity:
specific-sub-table:
五、查询类型
1. Devops/cpu-only
2. IoT