MxBench

MxBench — это инструмент для тестирования загрузки данных и выполнения запросов в MatrixDB. Он позволяет быстро генерировать случайные данные, автоматически создавать таблицы и выполнять последовательную или параллельную загрузку данных и выполнение запросов на основе пользовательских конфигураций, таких как количество устройств, временной диапазон и количество метрик. Пользователи могут гибко настраивать типы метрик, частоту сбора, долю значений NULL, уровень случайности, количество потоков запросов и кастомные запросы. MxBench можно запускать через командную строку или с помощью файла конфигурации. Инструмент расположен по пути bin/mxbench в каталоге установки MatrixDB.

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 на локальной машине разработчика, используйте файл конфигурации или интерфейс командной строки.

2.1.1 Файл конфигурации

Используйте следующий файл конфигурации, назовите его mxbench.conf и выполните команду:
mxbench --config mxbench.conf.
Примечание: параметр benchmark-parallel должен соответствовать возможностям машины; рекомендуется устанавливать значение, не превышающее количество ядер процессора.

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

[global]
  # Enable progress monitoring (default is true)
  watch = true

  # Directory to store generated DDL, GUC recommendations, queries, etc.
  workspace = "/tmp/mxbench"

  table-name = "table1"

  # Number of devices
  tag-num = 25000
  # Metric data type; supported: int4, int8, float4, float8
  metrics-type = "float8"
  # Total number of metrics; if greater than 998, first 997 are simple columns,
  # remaining stored in JSON format in a column named 'ext'
  total-metrics-count = 300

  # Start timestamp for generated data; ts-end must be later than ts-start
  ts-start = "2022-04-19 09:00:00"
  ts-end = "2022-04-19 09:03:00"

  # Interval between metric collections (in seconds)
  ts-step-in-second = "2"

[generator]
  generator = "telematics"

  [generator.telematics]
    # Number of batches per device per timestamp uploaded to DB (merged into one tuple)
    generator-batch-size = 1
    # Percentage of delayed data (1–100), with timestamps moved back by 1 hour
    generator-disorder-ratio = 0
    # Null value ratio in generated data (1–100)
    generator-empty-value-ratio = 90
    # Data randomness level: OFF/S/M/L; default is "OFF"; M is suitable for general scenarios
    generator-randomness = "OFF"

[writer]
  writer = "stdin"

[benchmark]
  benchmark = "telematics"

  [benchmark.telematics]
    # Array of query concurrency levels
    benchmark-parallel = [8]
    # Predefined queries: single-tag latest, 10-tag latest, single-tag detail
    benchmark-run-query-names = ["SINGLE_TAG_DETAIL_QUERY"]
    # Number of times each query runs per round, or duration in seconds
    # To enable runtime, set run-times to 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: Включает структуру таблицы, информацию об объёме данных и административные опции, такие как необходимость сохранять файлы данных, выполнять ли тесты и включать ли отслеживание прогресса;

Конфигурации на основе плагинов

  1. generator: Генератор данных:
  • telematics (по умолчанию) — генерирует данные для телематических сценариев;
  • file — читает данные из файлов;
  • nil — не генерирует никаких данных.
  1. writer: Записывает сгенерированные данные в MatrixDB через MxGate:
  • http (по умолчанию) — запускает MxGate по HTTP и загружает данные;
  • stdin — запускает MxGate через stdin и загружает данные;
  • nil — не запускает MxGate и не загружает данные.
  1. benchmark: Модуль на основе плагинов для генерации и выполнения запросов:
  • telematics (по умолчанию) — генерирует и выполняет типовые запросы для телематических сценариев, поддерживает кастомные запросы;
  • nil — не генерирует и не выполняет никаких запросов.

Ниже приведены подробные пояснения параметров каждого модуля:

2.2.1 database

[database]
  # Database name; MxBench creates it if it does not exist; no error if already exists  
  db-database = "postgres"

  ## Hostname where MatrixDB master instance resides
  db-master-host = "localhost"

  ## Port number of MatrixDB master instance
  db-master-port = 5432

  # MatrixDB user password
  db-password = ""

  # MatrixDB username
  db-user = "mxadmin"

2.2.2 global

[global]

  # Directory for MxBench-generated files including DDL, GUC restore scripts,
  # recommended GUC changes, CSV data files, and query files.
  # MxBench creates this directory if it does not exist; errors if path exists but is not a directory.
  # Permissions may need attention.
  # Each MxBench run creates a subdirectory named with Unix timestamp under this path.
  # Default: "/tmp/mxbench"
  workspace = "/tmp/mxbench"

  # Whether to dump CSV data files; options: true or false.
  # Default: false — executes DDL, data loading, and queries.
  # Under the timestamped subdirectory, generates:
  # 1. mxbench_ddl.sql: DDL script;
  # 2. mxbench_gucs_setup.sh: Recommended GUC settings script (may require restart to take effect);
  # 3. mxbench_gucs_backup.sh: Backup of current system GUCs; not generated if identical to recommendations;
  # 4. mxbench_<benchmark-plugin>_query.sql: Queries generated by the benchmark plugin.
  # If set to true, DDL, loading, and queries are not executed; additionally generates:
  # 5. mxbench_<generator-plugin>_data.csv: CSV data file from the generator plugin.
  dump = false

  # Whether to enable progress monitoring; options: true or false.
  # (Default) If true, prints execution progress of writer and benchmark modules every 5 seconds.
  # Set to false to disable.
  watch = true

  # Whether to run data loading and querying simultaneously; options: true or false.
  # If true: Runs mixed workload of loading and querying.
  # Queries loop until data loading finishes.
  # (Default) If false: Loads data first, then runs queries.
  simultaneous-loading-and-query = false

  # Path to custom DDL file.
  # (Default) If empty, DDL is auto-generated based on other configurations.
  ddl-file-path = ""

  # Type of metrics. Default: "float8" (double precision).
  # Only supports "int4", "int8", "float4", "float8".
  metrics-type = "float8"

  # Schema name; default: "public".
  schema-name = "public"

  # Table name. Default: ""; must be manually set.
  # If a table with the same name exists in the specified database and schema, MxBench exits with an error.
  table-name = "test_table"

  # Number of devices. Default: 25000.
  tag-num = 25000

  # Total number of metrics. Default: 300.
  # If greater than 998, excess metrics are stored as JSON in a column named "ext".
  # For example, if set to 1000, c0~c997 hold 998 simple columns,
  # and the remaining two are stored as JSON in the "ext" column.
  total-metrics-count = 300

  # Start timestamp for generated data. Generated data may precede this due to delayed reporting.
  ts-start = "2022-04-25 09:00:00"

  # End timestamp for generated data. ts-end must be later than ts-start, otherwise error.
  ts-end = "2022-04-25 09:01:00"

  # Interval between metric collections (in seconds). Default: "1".
  ts-step-in-second = "1"

2.2.3 generator

2.2.3.1 telematics (по умолчанию)

Генерирует данные для телематических сценариев. Используйте generator="telematics".

[generator]

  generator = "telematics"

  [generator.telematics]

    # Number of batches per device per timestamp sent to MatrixDB.
    # For example, if set to 5, data for device "tag1" at "2022-04-25 09:00:03"
    # is split into 5 rows and merged into one tuple in DB.
    # Default: 1 — no splitting.
    generator-batch-size = 1

    # Ratio of delayed reporting data. Value: 1–100.
    # Default: 0 — no delayed data.
    generator-disorder-ratio = 0

    # Null value ratio per row. Value: 1–100. Default: 90% — 90% of metrics are NULL.
    generator-empty-value-ratio = 90

    # Data randomness level: OFF/S/M/L. Default: OFF.
    generator-randomness = "OFF"
2.2.3.2 file

Читает данные из CSV-файлов. Используйте generator="file".

[generator]

  generator = "file"

  [generator.file]

    # Absolute paths to CSV data files. Accepts an array for multiple files.
    generator-file-paths = []

    # Same as [generator.telematics]; setting these is optional,
    # but helps generate better DDL. Has no effect if custom DDL is used.
    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 (по умолчанию)

Запускает MxGate по HTTP и загружает данные.

[writer]

  writer = "http"

  [writer.http]

    # Whether to use gzip compression when sending HTTP messages. Default: false.
    writer-use-gzip = false

    # Concurrency level when sending data to MxGate.
    writer-parallel = 8
2.2.4.2 stdin

Запускает MxGate через stdin и загружает данные.

[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]

    # List of telematics queries to execute sequentially.
    # Available queries:
    # 1. "SINGLE_TAG_LATEST_QUERY" 
    # 2. "MULTI_TAG_LATEST_QUERY" 
    # 3. "SINGLE_TAG_DETAIL_QUERY" 
    # These correspond to:
    # "SINGLE_TAG_LATEST_QUERY": Get latest metric values for one device;
    # "MULTI_TAG_LATEST_QUERY": Randomly select 10 devices and get their latest metric values;
    # "SINGLE_TAG_DETAIL_QUERY": Get metric values for one device over a time range.
    # Note: For very wide tables, retrieving all metrics at once may exceed DBMS limits.
    # Parameters below allow tuning the number of metrics and time range for "SINGLE_TAG_DETAIL_QUERY".
    # Example: [ "SINGLE_TAG_LATEST_QUERY", "MULTI_TAG_LATEST_QUERY", "SINGLE_TAG_DETAIL_QUERY" ] runs all three.
    # Remove names to skip corresponding queries. Invalid names are ignored.
    # Default: empty — no predefined queries executed.
    benchmark-run-query-names = [ "SINGLE_TAG_DETAIL_QUERY" ]

    # Custom queries, separated by commas.
    # Example: ["SELECT COUNT(*) FROM t1", "SELECT MAX(ts) FROM t1"]
    # Default: empty — no custom queries executed.
    benchmark-custom-queries = []

    # Query concurrency levels. Multiple values allowed, executed in order.
    # Example: [1, 8] runs queries first with concurrency 1, then 8.
    # Default: empty.
    benchmark-parallel = [8]

    # Number of times each query runs per concurrency level. Used for latency and TPS statistics.
    # Default: 0.
    benchmark-run-times = 0

    # Duration (seconds) each query runs per concurrency level. Statistics based on executions within this period.
    # Only effective when benchmark-run-times is 0. Default: 60 seconds.
    benchmark-runtime-in-second = "60"
2.2.5.2 nil

Установите benchmark = "nil", чтобы пропустить выполнение запросов.

[benchmark]

  benchmark = "nil"

2.3 Примеры файлов конфигурации

2.3.1 Генерация данных для широкой разреженной таблицы и выполнение смешанной нагрузки

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

[global]
  # Enable progress monitoring (default is true)
  watch = true

  # Directory for generated DDL, GUC best practices, queries, etc.
  workspace = "/home/mxadmin/mxbench/workspace"

  # Whether to run data loading and querying simultaneously
  simultaneous-loading-and-query = true

  table-name = "table2"

  # Number of devices
  tag-num = 20000
  # Metric data type; supports int4, int8, float4, float8
  metrics-type = "float8"
  # Number of metrics; if >998, first 997 are simple columns,
  # rest stored as JSON in a column named "ext"
  total-metrics-count = 5000

  # Start timestamp for generated data; ts-end must be later than ts-start
  ts-start = "2022-04-19 00:00:00"
  ts-end = "2022-04-19 00:01:00"

[generator]
  generator = "telematics"

  [generator.telematics]
    # Number of batches per device per timestamp; merged into one tuple in DB
    generator-batch-size = 1
    # Ratio of delayed data (1–100), timestamp shifted back by 1 hour
    generator-disorder-ratio = 0
    # Null value ratio in generated data (1–100)
    generator-empty-value-ratio = 90
    # Data randomness level: OFF/S/M/L; default: "OFF"
    generator-randomness = "OFF"

[writer]
  writer = "stdin"

[benchmark]
  benchmark = "telematics"

  [benchmark.telematics]
    # Array of query concurrency levels
    benchmark-parallel = [64]
    # Provided queries: single-tag latest, 10-tag latest, single-tag detail
    benchmark-run-query-names = [ "SINGLE_TAG_LATEST_QUERY", "MULTI_TAG_LATEST_QUERY", "SINGLE_TAG_DETAIL_QUERY" ]
    # Number of runs or duration per query per round; set runs to 0 to enable duration:
    benchmark-run-times = 0
    benchmark-runtime-in-second = "60"

2.3.2 Загрузка данных из внешнего CSV-файла с пользовательским DDL, без выполнения запросов

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

[generator]
  # Read data from CSV file
  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 Генерация данных для широкой разреженной таблицы и выполнение смешанной нагрузки

Запуск MxBench с примером конфигурации 1 эквивалентен следующей команде:

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 Загрузка данных из внешнего CSV-файла с пользовательским DDL, без выполнения запросов

Запуск MxBench с примером конфигурации 2 эквивалентен следующей команде:

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 Часто задаваемые вопросы

  1. Только загрузка, без запросов
    Установите benchmark = "nil".

  2. Только запросы, без загрузки
    Установите generator = "nil".

  3. Параллельное выполнение загрузки и запросов
    Установите simultaneous-loading-and-query = true в глобальных настройках.

  4. Генерация и сохранение CSV-файла с данными
    Установите dump = true в глобальных настройках. Выходной файл будет находиться в подкаталоге <unix-timestamp> внутри каталога workspace.

  5. Просмотр сгенерированных DDL и запросов
    Проверьте подкаталог <unix-timestamp> в каталоге workspace.

  6. Использование пользовательского DDL
    Укажите абсолютный путь к файлу DDL в параметре ddl-file-path в глобальных настройках.

  7. Выполнение пользовательских запросов
    Укажите кастомные запросы в параметре benchmark-custom-queries в разделе telematics benchmark, заключив их в кавычки. Подstitution параметров не поддерживается.

  8. Пропуск рекомендованных GUC и сохранение текущих
    Когда MxBench обнаруживает расхождения между текущими и рекомендованными GUC, он выводит предупреждение и спрашивает, нужно ли сбросить GUC и перезапустить базу данных. Введите "N", чтобы сохранить исходные GUC. MxBench затем уточнит, следует ли продолжить. Введите "Y", чтобы продолжить.

  9. Каковы требования к допустимости параметров?
    В глобальных настройках:

    • 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%

Объяснение: состоит из двух частей — отчёт о ходе записи и отчёт о ходе выполнения запросов.

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»: объём байтов, отправленных за этот период.

3.1.2 benchmark

Отображает ход выполнения запроса при заданном уровне параллелизма (parallel). При одновременном выполнении запросов и загрузки данных запросы могут циклически повторяться до завершения загрузки. Отчёт показывает прогресс только последней итерации.

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: время начала загрузки данных.
  • stop time: время окончания загрузки данных.
  • size written to MxGate (bytes): количество байтов, записанных в MxGate.
  • lines inserted: количество вставленных строк данных. Из-за операций upsert это число может превышать фактическое количество строк в базе данных.
  • compress ratio: коэффициент сжатия, определяемый как отношение объёма данных, записанных в MxGate, к фактическому размеру таблицы в базе данных.

3.2.2 benchmark

Для каждого запроса формируется отчёт в соответствии с настройкой 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.35972 мс означает, что 75% запросов выполнились быстрее этого значения, а 25% — медленнее. P50 — медианная задержка.
  • TPS: количество транзакций в секунду, то есть количество запросов, выполняемых в секунду.

Сводный отчёт:

┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│                                                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%                      │
└─────────────────────┴─────────────────────────────────────┴─────────────────────────────────────┴─────────────────────────────────────┘
  • Каждая строка показывает результаты выполнения всех запросов при определённом уровне параллелизма.
  • Каждый столбец показывает результаты выполнения конкретного запроса при разных уровнях параллелизма.
  • Если выполнение запросов проводилось в несколько циклов (например, в случае смешанной нагрузки, когда запросы выполняются непрерывно до завершения загрузки), отображаются только результаты последнего цикла.
  • Если выполнение запросов завершилось с ошибкой или было прервано пользователем, индикатор прогресса покажет текущий процент завершения, а статистика будет рассчитана только по завершённым запросам.