MxBench

MxBench 是MatrixDB数据加载和查询的压测工具,可以根据用户给定的设备数量、时间范围、指标数量配置快速生成随机数据,自动创建数据表,串行或并发进行数据加载和查询。用户可以灵活配置指标类型、采集频率、空值率、随机度等,还可以指定查询的线程数、定制查询语句等。MxBench可以通过命令行运行,也可以通过配置文件运行。该工具位于MatrixDB安装目录下的bin/mxbench。

1 准备

1.1 MatrixDB集群

需要一个正常运行的MatrixDB集群。

1.2 环境变量

由于MxBench需要调用createdb, gpconfig, gpstop,因此需要用户配置好相关环境变量使这些命令可以正确执行。

具体的,需要执行source <MatrixDB安装目录>/greenplum_path.sh, 还需要正确设置以下环境变量:

  • PGHOST
  • PGPORT
  • PGUSER
  • PGPASSWORD
  • PGDATABASE
  • MASTER_DATA_DIRECTORY

此外,用户还可以试执行 createdb mxbench, gpconfig -s log_rotation_size, gpstop -rai等命令,确保可以正确运行。

2 用法

2.1 快速试用

如果想在个人开发机上快速试用MxBench,可以使用配置文件或者命令行的方式运行MxBench.

2.1.1 配置文件

可以使用以下配置文件,命名为mxbench.conf,并运行: mxbench --config mxbench.conf. 注意benchmark-parallel参数设置需要适应机器性能,建议小于或等于CPU核数。

[database]
  db-database = "testdb1"
  db-master-port = 5432

[global]
  # 开启进度查看功能,默认即为true
  watch = true

  # 生成的DDL, GUCs设置建议, Query等文件的存放目录
  workspace = "/tmp/mxbench"

  table-name = "table1"

  # 设备数
  tag-num = 25000
  # 指标数据类型,支持 int4, int8, float4, float8 四种类型
  metrics-type = "float8"
  # 指标数目,如果指标数大于998,就把前997个作为简单列,
  # 其他的作为json存放在名为ext的列中
  total-metrics-count = 300

  # 生成数据的起始时间戳, ts-end必须晚于ts-start,否则报错
  ts-start = "2022-04-19 09:00:00"
  ts-end = "2022-04-19 09:03:00"

  # 每几秒采集一次指标
  ts-step-in-second = "2"

[generator]
  generator = "telematics"

  [generator.telematics]
    # 每个设备每个时间点的指标,分几条数据上传,最终在DB被upsert成1个tuple
    generator-batch-size = 1
    # 延迟上传的数据生成比例(1~100),时间戳往前推1小时
    generator-disorder-ratio = 0
    # 生成数据的空值率(1~100)
    generator-empty-value-ratio = 90
    # 生成数据的随机度, 有OFF/S/M/L几档,默认关闭"OFF", 一般场景可选择M档
    generator-randomness = "OFF"

[writer]
  writer = "stdin"

[benchmark]
  benchmark = "telematics"

  [benchmark.telematics]
    # 数组,查询并发度
    benchmark-parallel = [8]
    # 提供的3个查询:单车最新值,10车最新值,单车明细
    benchmark-run-query-names = ["SINGLE_TAG_DETAIL_QUERY" ]
    # 每轮每条query的跑的次数或时间,让时间生效需要将次数设置为0,如下:
    benchmark-run-times = 0
    benchmark-runtime-in-second = "30"

2.1.2 命令行

还可以使用命令行运行MxBench。运行以下命令就等同于以上面的配置文件运行MxBench。

mxbench run \
  --db-database "testdb1" \
  --db-master-host "localhost" \
  --db-master-port 5432 \
  --db-user "mxadmin" \
  --workspace "/tmp/mxbench" \
  --table-name "table1" \
  --ts-start "2022-04-19 09:00:00" \
  --ts-end "2022-04-19 09:02:00" \
  --ts-step-in-second 2 \
  --generator "telematics" \
  --writer "stdin" \
  --benchmark "telematics" \
  --benchmark-run-query-names "SINGLE_TAG_DETAIL_QUERY" \
  --benchmark-parallel 8 \
  --benchmark-run-times 0 \
  --benchmark-runtime-in-second 30

2.2 配置详解

从示例配置文件可以看到,配置文件分为以下几个板块:

全局配置

  1. database: 数据库相关的配置;
  2. global: 包括一些表结构、数据量信息,以及是否dump数据文件或实际执行测试、是否开启进度观察等管理方面的配置;

可插件化的配置

  1. generator: 数据生成器:
  • telematics(默认) - 生成车联网场景的数据;
  • file - 从文件中读取数据;
  • nil - 不生成数据。
  1. writer: 负责把生成的数据通过MxGate写入MatrixDB:
  • http(默认) - 以HTTP的方式启动MxGate,并通过其加载数据至MatrixDB;
  • stdin - 以stdin的方式启动MxGate,并通过其加载数据至MatrixDB;
  • nil - 不启动MxGate,不加载。
  1. benchmark: 可插件化,生成并执行query语句:
  • telematics(默认) - 生成并执行车辆网场景下的常用query,支持定制query;
  • nil - 不生成、不执行query语句。

以下是各模块参数详解:

2.2.1 database

[database]
  # 数据库名称,如果不存在,MxBench会自动创建;已存在也不会报错  
  db-database = "postgres"

  ## MatrixDB master实例所在主机的hostname
  db-master-host = "localhost"

  ## MatrixDB master 实例的端口号
  db-master-port = 5432

  # MatrixDB 用户密码
  db-password = ""

  # MatrixDB 用户名
  db-user = "mxadmin"

2.2.2 global

[global]

  # MxBench 生成DDL文件,现有系统GUCs恢复脚本, 最佳实践推荐GUCs更改脚本,
  # csv数据文件,query文件的目录。
  # 如果不存在,MxBench会自动创建;如果已存在且非目录,则会报错。可能需要注意权限问题。
  # 每次运行MxBench,都会在其下创建名为Unix时间戳的目录,该次运行生成的文件都会在该目录下。
  # 默认为"/tmp/mxbench"
  workspace = "/tmp/mxbench"

  # 是否dump csv数据文件,可选true或false。
  # 默认为false,会执行DDL、数据加载、query。
  # 在workspace下Unix时间戳的目录中,会生成:DDL、GUCs相关脚本和query文件。
  # 1. mxbench_ddl.sql: DDL文件;
  # 2. mxbench_gucs_setup.sh: 最佳实践推荐的GUCs设置脚本,可能需要再重启MatrixDB才能全部生效。
  # 3. mxbench_gucs_backup.sh: 现有系统GUCs备份。如果现有系统的GUCs和最佳实践的GUCs一致,便不会生成。
  # 4. mxbench_<benchmark-plugin>_query.sql: 相应benchmark插件生成的query语句。
  # 如果选择true,则不会实际执行DDL、数据加载以及query;除了上面的各文件,还会生成:
  # 5. mxbench_<generator-plugin>_data.csv: 相应generator插件生成的data的csv文件。
  dump = false

  # 是否开启进程观察,可选true或false。
  #(默认)如果选择true,则会每5秒打印一次writer和benchmark模块的执行进度信息。
  # 选择false关闭。
  watch = true

  # 是否同时执行数据加载和查询,可选true或false。
  # 如果选择true: 执行数据加载和查询的混合负载
  # query跑完之后会再循环跑,直到数据加载结束。
  # (默认)如果选择false: 先执行数据加载,执行完毕后再执行查询。
  simultaneous-loading-and-query = false

  # 如果需要定制DDL,该参数填写DDL文件的路径。
  # (默认)不填写则会根据其他相关配置生成DDL。
  ddl-file-path = ""

  # 指标的类型。默认为"float8",即双精度浮点数。
  # 只支持 "int4", "int8", "float4", "float8", 4种类型.
  metrics-type = "float8"

  # schema名称,默认为"public".
  schema-name = "public"

  # 数据表名称。默认为"", 必须手动设置。
  # 如果该同名表在配置的数据库、schema下存在,会报错,终止MxBench程序。
  table-name = "test_table"

  # 设备数量。默认25000.
  tag-num = 25000

  # 指标总数。默认300.
  # 如果指标总数大于998,则超过部分的指标会以json类型存放在名为"ext"的列中。
  # 例如,如果指标总数设为1000,则998个会以简单列形式存放在名为c0~c997的列中,
  # 其他2个以json形式放在ext的json类型的列中。
  total-metrics-count = 300

  # 生成数据时间戳起始时间。因为有延迟上报的数据存在,生成数据可能会早于这个时间。
  ts-start = "2022-04-25 09:00:00"

  # 生成数据时间戳终止时间。ts-end必须晚于ts-start,否则报错
  ts-end = "2022-04-25 09:01:00"

  # 每几秒采集一次指标。默认为"1"。
  ts-step-in-second = "1"

2.2.3 generator

2.2.3.1 telematics(默认)

生成车联网场景数据,选择generator="telematics"。

[generator]

  generator = "telematics"

  [generator.telematics]

    # 每个设备在每个时间戳的指标,分几条上传至MatrixDB。
    # 例如,如果设置为5,名为"tag1"的设备在"2022-04-25 09:00:03"这个时间戳下,
    # 各个指标的数据会分5条传到MatrixDB,最终合并为1个tuple.
    # 默认为1. 即指标信息不做拆分。
    generator-batch-size = 1

    # 延迟上报数据的比例。取值1~100.
    # 默认值为0, 即没有延迟上报的数据。
    generator-disorder-ratio = 0

    # 每行数据的空值率。取值为1~100. 默认为90%,即90%的指标都将是空值。
    generator-empty-value-ratio = 90

    # 指标数据随机度, 分为OFF/S/M/L四档。默认为OFF。
    generator-randomness = "OFF"
2.2.3.2 file

从csv文件中读取数据并加载,选择generator="file"。

[generator]

  generator = "file"

  [generator.file]

    # 数据csv数据的绝对路径。可接收一个数组,即上传多个csv文件。
    generator-file-paths = []

    # 同[generator.telematics],设置这两个参数非必需,
    # 但是妥当设置会帮助我们更好的生成DDL语句。如选定制DDL语句则将不起作用。
    generator-batch-size = 1
    generator-empty-value-ratio = 90
2.2.3.3 nil

不生成、加载任何数据,选择generator="nil"。

[generator]

  generator = "nil"

2.2.4 writer

2.2.4.1 http(默认)

以http形式启动MxGate并加载数据。

[writer]

  writer = "http"

  [writer.http]

    # 发送http消息是否使用gzip压缩,默认不采用
    writer-use-gzip = false

    # 向MxGate发送数据的并发度。
    writer-parallel = 8
2.2.4.2 stdin

以stdin方式启动MxGate并加载数据。

[writer]

  writer = "stdin"
2.2.4.3 nil

不启动MxGate,不写入数据。

[writer]

  writer = "nil"

2.2.5 benchmark

2.2.5.1 telematics(默认)
[benchmark]

  benchmark = "telematics"

  [benchmark.telematics]

    # 将要顺序执行的telematics提供的query名称,
    # 现提供:
    # 1. "SINGLE_TAG_LATEST_QUERY" 
    # 2. "MULTI_TAG_LATEST_QUERY" 
    # 3. "SINGLE_TAG_DETAIL_QUERY" 
    # 共3个合法query名,分别为:
    # "SINGLE_TAG_LATEST_QUERY": 获得单车最近时间戳的各个指标值;
    # "MULTI_TAG_LATEST_QUERY": 随机选取10车,获得其最近时间戳的各个指标值;
    # "SINGLE_TAG_DETAIL_QUERY": 获得单车在一段时间内的各个指标的值。
    # 注:对于超宽表,指标数很多,可能DBMS不支持一次获取所有指标值,
    # 因此下面由参数可以调试获取的指标数以及"SINGLE_TAG_DETAIL_QUERY"的时间段取值。
    # 例如,输入[ "SINGLE_TAG_LATEST_QUERY", "MULTI_TAG_LATEST_QUERY", "SINGLE_TAG_DETAIL_QUERY" ] 就可以顺序执行上述三个query。
    # 在此基础上删减query名称便可不执行对应query。输入其他名称会被忽略。
    # 默认为空,即不执行任何预设query。
    benchmark-run-query-names = [ "SINGLE_TAG_DETAIL_QUERY" ]

    # 定制query,使用"," 分隔。
    # 例如, ["SELECT COUNT(*) from t1", "SELECT MAX(ts) from t1"]
    # 默认为空,即不执行任何定制query.
    benchmark-custom-queries = []

    # 跑query的并发度,可以输入多个,顺序对应并发度执行各个query,使用","分隔。
    # 例如,输入 [1, 8] 就可以先以并发度1跑各个query,再以并发度为8跑各个query。
    # 默认为空。
    benchmark-parallel = [8]

    # 每个query在每个并发度下跑的次数,根据这么多次跑的结果做延迟和TPS统计,默认为0。
    benchmark-run-times = 0

    # 每个query在每个并发度下跑的时间(秒), 根据这段时间内query执行的结果做延迟和TPS统计。
    # 只在benchmark-run-times为0的情况下才生效。默认为60,即每个query在每个并发度下跑60秒。
    benchmark-runtime-in-second = "60"
2.2.5.2 nil

如果不需要执行任何query,则将benchmark设为nil。

[benchmark]

  benchmark = "nil"

2.3 示例配置文件

2.3.1 超宽稀疏表生成数据并运行混合负载

[database]
  db-database = "testdb2"
  db-master-port = 5432

[global]
  # 开启进度查看功能,默认即为true
  watch = true

  # 生成的DDL, GUCs最佳实践建议, Query等文件的存放目录
  workspace = "/home/mxadmin/mxbench/workspace"

  # 数据加载和查询是否同时进行
  simultaneous-loading-and-query = true

  table-name = "table2"

  # 设备数
  tag-num = 20000
  # 指标数据类型,支持 int4, int8, float4, float8 四种类型
  metrics-type = "float8"
  # 指标数目,如果指标数大于998,就把前997个作为简单列,
  # 其他的作为json存放在名为ext的列中
  total-metrics-count = 5000

  # 生成数据的起始时间戳,ts-end必须晚于ts-start,否则报错
  ts-start = "2022-04-19 00:00:00"
  ts-end = "2022-04-19 00:01:00"

[generator]
  generator = "telematics"

  [generator.telematics]
    # 每个设备每个时间点的指标,分几条数据上传,最终在DB被upsert成1个tuple
    generator-batch-size = 1
    # 延迟上传的数据生成比例(1~100),时间戳往前推1小时
    generator-disorder-ratio = 0
    # 生成数据的空值率(1~100)
    generator-empty-value-ratio = 90
    # 生成数据的随机度, 有OFF/S/M/L几档,默认关闭"OFF"
    generator-randomness = "OFF"

[writer]
  writer = "stdin"

[benchmark]
  benchmark = "telematics"

  [benchmark.telematics]
    # 数组,查询并发度
    benchmark-parallel = [64]
    # 提供的3个查询:单车最新值,10车最新值,单车明细
    benchmark-run-query-names = [ "SINGLE_TAG_LATEST_QUERY", "MULTI_TAG_LATEST_QUERY", "SINGLE_TAG_DETAIL_QUERY" ]
    # 每轮每条query的跑的次数或时间,让时间生效需要将次数设置为0,如下:
    benchmark-run-times = 0
    benchmark-runtime-in-second = "60"

2.3.2 从外部读取DDL并外部读取csv文件加载,不跑查询

[database]
  db-database = "testdb3"
  db-master-port = 5432

[generator]
  # 从csv文件中读取数据
  generator = "file"

  [generator.file]
    generator-file-paths = ["/home/mxadmin/mxbench/data.csv"]


[global]

  table-name = "table3"

  watch = true
  workspace = "/home/mxadmin/mxbench/workspace"
  ddl-file-path = "/home/mxadmin/mxbench/ddl.sql"

[writer]
  writer = "stdin"

[benchmark]
  benchmark = "nil"

2.4 示例命令行

2.4.1 超宽稀疏表生成数据并运行混合负载

使用示例配置文件1运行MxBench相当于使用以下命令行运行MxBench:

mxbench run \
  --db-database "testdb2" \
  --db-master-port 5432 \
  --db-user "mxadmin" \
  --workspace "/home/mxadmin/mxbench/workspace" \
  --simultaneous-loading-and-query \
  --table-name "table2" \
  --tag-num 25000 \
  --metrics-type "float8" \
  --total-metrics-count 5000 \
  --ts-start "2022-04-19 00:00:00" \
  --ts-end "2022-04-19 00:01:00" \
  --generator "telematics" \
  --generator-batch-size 1 \
  --generator-disorder-ratio 0 \
  --generator-empty-value-ratio 90 \
  --generator-randomness "OFF" \
  --writer "stdin" \
  --benchmark "telematics" \
  --benchmark-run-query-names "SINGLE_TAG_LATEST_QUERY" \
  --benchmark-run-query-names "MULTI_TAG_LATEST_QUERY" \
  --benchmark-run-query-names "SINGLE_TAG_DETAIL_QUERY" \
  --benchmark-parallel 64 \
  --benchmark-run-times 0 \
  --benchmark-runtime-in-second 60

2.4.2 从外部读取DDL并外部读取csv文件加载,不跑查询

使用示例配置文件2运行MxBench相当于使用以下命令行运行MxBench:

mxbench run \
  --db-database "testdb3" \
  --db-master-port 5432 \
  --workspace "/home/mxadmin/mxbench/workspace" \
  --ddl-file-path "/home/mxadmin/mxbench/ddl.sql" \
  --table-name "table3" \
  --generator "file" \
  --generator-file-paths "/home/mxadmin/mxbench/data.csv" \
  --writer "stdin" \
  --benchmark "nil" 

2.5 FAQ

  1. 只加载,不查询 将benchmark设为nil;

  2. 只查询,不加载 将generator设为nil;

  3. 加载和查询同时跑 global设置中simultaneous-loading-and-query为true。

  4. 想要生成并dump出csv数据文件 global设置中dump为true, 生成的文件在workspace设置的目录下的目录中。

  5. 想要查看生成的ddl和query workspace设置的目录下的目录中。

  6. 想要跑定制DDL 在global设置中的ddl-file-path中填写ddl文件的绝对路径。

  7. 想要跑定制query 在 telematics benchmark的 benchmark-custom-queries中填写定制query语句, 用""括起来。不支持随机参数。

  8. 不想采用系统建议的GUCs, 保留现有GUCs运行mxbench: MxBench检测到现有系统和建议GUCs有不一致时,会在标准输出中做提示,并且询问是否需要重设GUCs并启动数据库。输入"N",保留原有GUCs. MxBench这时还会再次确认是否继续运行MxBench。选择"Y", 继续运行。

  9. 对参数合法性有什么要求? global 配置里:

  • ts-end必须晚于ts-start;
  • table-name、schema-name 不为空;
  • tag-num必须大于0;
  • ts-step-in-second不为0。

3 理解进度信息和统计报告

3.1 进度信息

示例:

● Stdin Writer Report
  ● period start: 2022-04-29 10:08:11, end: 2022-04-29 10:08:16, period: 5.000129734s

  ● count written in total: 637025 rows/ 1500000 rows 42%, 637025 rows in this period

  ● size written in total: 160878718 bytes/ 360000003 bytes 44%, 160878718 bytes in this period

  ● size written to MxGate in total: 350075440 bytes, 350075440 bytes in this period

● Telematics Benchmark Report
  ● stats for query SINGLE_TAG_LATEST_QUERY with parallel 8: progress: 100%

  ● stats for query MULTI_TAG_LATEST_QUERY with parallel 8: progress: 43%

说明:总共由两部分组成,即writer和benchamrk的进度报告。

3.1.1 writer

  • period start, period end, period: 该统计窗口的起止时间和时间段;
  • count written: 已经写入的数据行数和预计数据行数,以及二者的百分比。xx in this period:该统计窗口内写入的行数;
  • size written: 已经写入的数据字节数和预计数据字节数,以及二者的百分比。xx in this period: 该统计窗口内写入的字节数;
  • size written to MxGate: 把数据转化成文本后写入MxGate的字节数。xx in this period: 该统计窗口内写入MxGate的字节数。

3.1.2 benchmark

某条query在某并发度parallel参数下的执行进度。query与数据加载同时进行时,query会在数据加载结束之前一直进行,因此可能会循环运行多轮。该进度报告只显示最近一轮的进度报告

3.2 统计报告

3.2.1 writer

┌───────────────────────────────────────────────────────┐
│            Summary Report for Stdin Writer            │
├─────────────────────────────────┬─────────────────────┤
│ start time:                     │ 2022-04-27 13:29:01 │
├─────────────────────────────────┼─────────────────────┤
│ stop time:                      │ 2022-04-27 13:29:58 │
├─────────────────────────────────┼─────────────────────┤
│ size written to MxGate (bytes): │ 848333400           │
├─────────────────────────────────┼─────────────────────┤
│ lines inserted:                 │ 1500000             │
├─────────────────────────────────┼─────────────────────┤
│ compress ratio:                 │ 1.561276 : 1        │
└─────────────────────────────────┴─────────────────────┘
  • start time: 数据加载起始时间;
  • end time: 数据加载终止时间;
  • size written to MxGate (bytes): 向MxGate写入数据的字节数;
  • lines inserted: 插入数据的条数. 由于upsert可能存在,这一数字可能会高于数据库中实际的数据条数。
  • compress ratio: 压缩比,即向MxGate写入数据的大小和实际数据库中该表的大小的比值。

3.2.2 benchmark

每条query,在每个parallel参数下都会产生一个报告,会实时打印出来。

┌─────────────────┬───────────────┐
│ Overall Latency │ 29.948370582s │
│ Average Latency │   13.723304ms │
│ P75 Latency     │    14.35972ms │
│ P50 Latency     │   13.654556ms │
│ P25 Latency     │   12.925912ms │
│ TPS             │           582 │
└─────────────────┴───────────────┘
  • Pxx 代表xx百分位数的延迟。例如P75是14.35972ms,说明执行query的次数中,有25%延迟高于它,75%低于它. P50即中位数。
  • TPS: 每秒执行query的次数.

汇总报告:

┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│                                                Summary Report for Telematics Benchmark                                                │
├─────────────────────┬─────────────────────────────────────┬─────────────────────────────────────┬─────────────────────────────────────┤
│ Parallel\Query Name │ SINGLE_TAG_LATEST_QUERY             │ MULTI_TAG_LATEST_QUERY              │ SINGLE_TAG_DETAIL_QUERY             │
├─────────────────────┼─────────────────────────────────────┼─────────────────────────────────────┼─────────────────────────────────────┤
│ 8                   │ ┌─────────────────┬───────────────┐ │ ┌─────────────────┬───────────────┐ │ ┌─────────────────┬───────────────┐ │
│                     │ │ Overall Latency │ 30.008625133s │ │ │ Overall Latency │ 36.407016561s │ │ │ Overall Latency │ 29.948370582s │ │
│                     │ │ Average Latency │    23.81758ms │ │ │ Average Latency │  7.270212105s │ │ │ Average Latency │   13.723304ms │ │
│                     │ │ P75 Latency     │   24.911171ms │ │ │ P75 Latency     │  8.139682559s │ │ │ P75 Latency     │    14.35972ms │ │
│                     │ │ P50 Latency     │   23.411248ms │ │ │ P50 Latency     │  7.161237157s │ │ │ P50 Latency     │   13.654556ms │ │
│                     │ │ P25 Latency     │   20.899622ms │ │ │ P25 Latency     │  6.642459805s │ │ │ P25 Latency     │   12.925912ms │ │
│                     │ │ TPS             │           335 │ │ │ TPS             │             1 │ │ │ TPS             │           582 │ │
│                     │ └─────────────────┴───────────────┘ │ └─────────────────┴───────────────┘ │ └─────────────────┴───────────────┘ │
│                     │ progress: 100%                      │ progress: 100%                      │ progress: 100%                      │
└─────────────────────┴─────────────────────────────────────┴─────────────────────────────────────┴─────────────────────────────────────┘
  • 每行代表某并发度下各query的执行结果。
  • 每列代表每个query在各个并发度下的执行结果。
  • 如果query集执行了多轮(混合负载的情况下,数据加载未结束,query便会一直执行),则仅展示最后一轮的结果。
  • 如果因为query执行错误或者用户中断执行,进度条会显示当前进度,统计信息是根据已经执行query的做出统计。