Пользовательская нагрузка

Позволяет провести нагрузочное тестирование по заданному пользовательскому сценарию.

Сценарий тестирования представляет собой директорию, называемую suite, которая содержит набор поддиректорий: init, import и run, соответствующих командам ydb workload query.

  • Директория init может иметь произвольную структуру и содержит SQL-запросы создания и настройки объектов в базе данных, таких как таблицы или индексы.
  • Директория import содержит данные для загрузки в таблицы. Каждой таблице соответствует поддиректория в директории import.
  • Директория run может иметь произвольную структуру и содержит SQL-запросы для нагрузочного тестирования.

Пример директории suite на GitHub.

Пользователь указывает путь к директории suite с помощью опции --suite-path в каждой команде.

Общий синтаксис

Общий синтаксис вызова команд пользовательской нагрузки:

ydb [global options...] workload query [--path <путь/в/бд>] <команда> [options...]
  • global optionsглобальные параметры.
  • --path — путь в базе данных для объектов нагрузочного тестирования.
  • <команда> — одна из команд: init, import, run, clean.
  • options — параметры конкретной команды.

Общие параметры команд

Все команды поддерживают общий параметр --path, который задает путь в базе данных для объектов нагрузочного тестирования. Все создаваемые объекты будут созданы по этому пути. Также путь будет учтен при выполнении теста и очистке.

Доступные параметры

Имя Описание Значение по умолчанию
--path или -p Путь в базе данных для объектов нагрузочного тестирования. /

Инициализация нагрузочного теста

Перед запуском теста создайте таблицы и другие объекты базы данных:

ydb workload query --path user_path init --suite-path ~/user-suite

Команда init действует следующим образом:

  • Если задан suite и в нем присутствует директория init, производится сканирование директории init с учетом её вложенных директорий поиском в глубину с лексиографическим упорядочиванием файлов и поддиректорий на каждом уровне.
  • Выбираются файлы с расширениями sql и yql.
  • Содержимое каждого файла считывается и последовательно исполняется как SQL-запрос.
  • После этого выполняются запросы, заданные напрямую из командной строки с помощью параметра --query.
  • Если какой-либо из запросов приводит к ошибке, то выполнение команды прекращается.

Предполагается, что на этом этапе выполняются относительно "лёгкие" запросы, например, создание таблиц и индексов. Не рекомендуется включать в состав файлов в директории init скрипты с наполнением таблиц данными. Эти операции следует перенести на фазу import.

В запросах могут быть использованы макросы:

  • {db} — Абсолютный путь в базе данных к директории тестирования. Представляет собой комбинацию значений опций --database и --path.

Посмотрите описание команды для инициализации таблиц:

ydb workload query init --help

Доступные параметры

Имя Описание Значение по умолчанию
--suite-path <путь> Путь к suite-директории.
--query <запрос> или -q <запрос> DDL-запрос для выполнения. Может быть использован несколько раз.
--clear Если по указанному пути создаваемая таблица уже существует, она будет предварительно удалена.
--dry-run Не выполнять инициализационные запросы, а только распечатать их.

Загрузка данных в таблицу

Загрузите данные в таблицы:

ydb workload query --path user_path import --suite-path ~/user-suite

Команда import действует следующим образом:

  • Если задан suite и в нем присутствует директория import, она выполняет последовательный обход её поддиректорий.
  • Предполагается, что каждая поддиректория соответствует таблице в базе данных. Путь к поддиректории от директории suite совпадает с путем к таблице от корня базы данных.
  • В поддиректории используются файлы в поддерживаемых форматах данных, а именно csv, tsv, csv.gz, tsv.gz и parquet.
  • Выполняется загрузка данных из файлов в соответствующие таблицы. Загрузка идет во много потоков, причем параллелится как загрузка разных файлов, так и частей одного файла. Порядок загрузки не гарантируется.

Процесс загрузки может продолжаться длительное время и быть по какой-то причине прерван. Для того чтобы иметь возможность продолжить загрузку с момента остановки, может быть применен механизм состояния. При помощи опции --state можно указать путь к файлу состояния. Если файл состояния существует, то он будет использован для продолжения загрузки. Если файла состояния нет, то он будет создан в процессе загрузки. Также он может быть очищен с помощью опции --clear-state.

Посмотрите описание команды для загрузки данных:

ydb workload query import --help

Доступные параметры

Имя Описание Значение по умолчанию
--suite-path <путь> Путь к suite-директории.
--state <путь> Путь к файлу состояния загрузки. Если загрузка была прервана по какой-то причине, при новом запуске загрузка будет продолжена с того же места.
--clear-state Актуально, если задан параметр --state. Очистить файл состояния и начать загрузку сначала.
--dry-run Не выполнять загрузку данных в базу данных, только подготовить данные и вывести об этом сообщение.

Общие параметры команды import

Имя Описание Значение по умолчанию
--upload-threads <значение> или -t <значение> Количество потоков исполнения для подготовки данных. Рассчитывает автоматически и равно числу доступных ядер на клиентской машине.
--bulk-size <значение> Размер порции для отправки данных в строках. 10000
--max-in-flight <значение> Максимальное количество порций данных, одновременно находящихся в обработке. 128
--file-output-path <значение> или -f <путь> Если эта опция установлена, данные не будут загружены в базу данных, а будут сохранены в каталоге <путь>.

Запуск нагрузочного теста

Запустите нагрузку:

ydb workload query --path user_path run --suite-path ~/user-suite

Команда run действует следующим образом:

  • Если в suite присутствует директория run, команда выполняет обход её и всех её вложенных директорий поиском в глубину, на каждом уровне упорядочивая файлы и поддиректории по алфавиту. В случае отсутствия директории run, выполнение прекращается.
  • Выбирает файлы с расширениями sql и yql и включает их в список SQL-запросов.
  • После этого добавляет в список запросы, заданные напрямую из командной строки с помощью параметра --query.
  • В зависимости от опций либо выполняет все запросы последовательно, каждый запрос заданное число раз, либо параллельно в несколько потоков с перемешиванием запросов.
  • Ошибки в запросах будут учтены в статистике, но не приводят к остановке тестирования.

В течение теста на экран выводится статистика по нагрузке для каждого запроса и агрегированная статистика по всем запросам.

Посмотрите описание команды для запуска нагрузки:

ydb workload query run --help

Общие параметры для всех видов нагрузки

Имя Описание Значение по умолчанию
--dry-run Не выполнять инициализационные запросы, а только вывести их текст.
--check-canonical или -c Использовать специальную версию запросов (они имеют детерминированные ответы) и сверять результаты с каноническими.
--output <значение> Имя файла, в котором будут сохранены результаты выполнения запросов. results.out
--iterations <значение> Количество выполнений каждого из запросов нагрузки. 1
--json <имя> Имя файла, в котором будет сохранена статистика выполнения запросов в формате json. Файл не сохраняется
--ministat <имя> Имя файла, в котором будет сохранена статистика выполнения запросов в формате ministat. Файл не сохраняется
--csv <имя> Имя файла для сохранения CSV-версии таблицы с результатами. Файл не сохраняется
--plan <имя> Имя файла для сохранения плана запроса. Если задано, то сохраняются файлы <имя>.<номер запроса>.explain и <имя>.<номер запроса>.<номер итерации> с планами в нескольких форматах: ast, json, svg и table. Планы не сохраняется.
--query-prefix <префикс> Префикс запроса. Каждый префикс будет добавлен отдельной строкой в начало каждого запроса. Если нужно указать несколько префиксов, используйте параметр несколько раз. По умолчанию не задан
--retries Количество повторных попыток выполнения каждого запроса 0
--include Имена, номера или диапазоны номеров запросов, которые нужно выполнить в рамках нагрузки. Указываются через запятую, например: 1,2,4-6. Все запросы
--exclude Имена, номера или диапазоны номеров запросов, которые нужно исключить из нагрузки. Указываются через запятую, например: 1,2,4-6.
--verbose или -v Выводить больше информации на экран в процессе выполнения запросов.
--global-timeout <значение> Общий таймаут на выполнение всех запросов. Задаётся в текстовом формате, например: 0.5s, 1m, 100us и т.д. Отсутствует. Время не ограничино.
--request-timeout <значение> Таймаут на выполнение каждой итерации каждого запроса. Задаётся в текстовом формате, например: 0.5s, 1m, 100us и т.д. Отсутствует. Время не ограничино.
--threads <значение> или -t <значение> Количество потоков, генерирующих нагрузку. Ноль означает, что запросы будут выполняться в основном потоке; при ином значении запросы будут перемешаны. 0

Опции, специфичные для Query

Имя Описание Значение по умолчанию
--suite-path <путь> Путь к suite-директории.
--query <запрос> или -q <запрос> Запрос для выполнения. Может быть использован несколько раз.

Канонические результаты

Для каждого запроса из файла может быть задан канонический (ожидаемый) результат. Если ответ на запрос не соответствует каноническому, это будет отражено в статистике и в выводе команды. Также будут приведены отличия.

Канонический результат задается с помощью файла с тем же именем и дополнительным расширением .result. Это файлы CSV с заголовками и некоторым дополнительным синтаксисом:

  • Если запрос имеет более одного набора результатов, файл результатов должен содержать соответствующее количество наборов данных, разделенных пустыми строками.

    Например, запрос

    SELECT COUNT(*) AS count FROM table_1;
    SELECT MIN(col1) AS min, MAX(col1) AS max FROM table_2;
    

    Может иметь следующий файл результатов:

    count
    10
    
    min,max
    4,5
    
  • Последняя строка может быть задана как ..., что означает, что результат запроса может иметь больше строк, чем в каноническом результате, но первые строки результата должны соответствовать каноническим.

  • По умолчанию числа с плавающей точкой сравниваются с относительной точностью 1e-3 процента, но в каноническом результате вы можете указать любую абсолютную или относительную точность для каждого значения, например: 1.5+-0.01, 2.4e+10+-1%.

Для запросов, заданных опцией --query, канонический результат не может быть задан.

Канонический результат не будет использоваться, если не установлен флаг --check-canonical.

Очистка данных теста

Запустите очистку:

ydb workload query --path user_path clean

Выполняет рекурсивное удаление объектов базы данных по указанному в параметре --path пути.

Команда не имеет параметров.

Пример запуска пользовательского теста

Скачайте пример из репозитория

git clone https://github.com/ydb-platform/ydb.git
cd ydb/ydb/tests/functional/tpc/data/e1

Запустите инициализацию

ydb workload query --path test_path init --suite-path .

Результат:

Init tables ...
Init tables ...Ok

Запустите импорт данных

ydb workload query --path test_path import --suite-path .

Результат:

Fill table test_table_1...
Fill table test_table_1 OK 0 / 0 (0.353816s)
Fill table test_table_2...

Fill table test_table_2 OK 0 / 0 (0.102385s)

Запустите нагрузочный тест

ydb workload query --path user_path run --suite-path e1

Результат:

first_query_set.1.sql:
    iteration 0:    ok    0.131573s seconds
first_query_set.2.yql:
    iteration 0:    ok    0.089327s seconds
second_query_set.join.sql:
    iteration 0:    ok    0.145536s seconds

Results for 1 iterations
┌───────────────────────────┬──────────┬─────────┬─────────┬─────────┬─────────┬───────────┬─────────┬─────────┬─────────┬─────────┬────────────────┬────────────────┬────────────────┬───────────┬──────────────┬────────────┬────────────┐
│ Query #                   │ ColdTime │ Min     │ Max     │ Mean    │ Median  │ UnixBench │ Std     │ RttMin  │ RttMax  │ RttAvg  │ CompilationMin │ CompilationMax │ CompilationAvg │ GrossTime │ SuccessCount │ FailsCount │ DiffsCount │
├───────────────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┼───────────┼─────────┼─────────┼─────────┼─────────┼────────────────┼────────────────┼────────────────┼───────────┼──────────────┼────────────┼────────────┤
│ first_query_set.1.sql     │   0.086  │   0.086 │   0.086 │   0.086 │   0.086 │   0.086   │   0.000 │   0.045 │   0.045 │   0.045 │   0.041        │   0.041        │   0.041        │   0.132   │ 1            │            │            │
├───────────────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┼───────────┼─────────┼─────────┼─────────┼─────────┼────────────────┼────────────────┼────────────────┼───────────┼──────────────┼────────────┼────────────┤
│ first_query_set.2.yql     │   0.081  │   0.081 │   0.081 │   0.081 │   0.080 │   0.081   │   0.001 │   0.008 │   0.008 │   0.008 │   0.039        │   0.039        │   0.039        │   0.089   │ 1            │            │            │
├───────────────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┼───────────┼─────────┼─────────┼─────────┼─────────┼────────────────┼────────────────┼────────────────┼───────────┼──────────────┼────────────┼────────────┤
│ second_query_set.join.sql │   0.131  │   0.131 │   0.131 │   0.131 │   0.131 │   0.131   │   0.000 │   0.014 │   0.014 │   0.014 │   0.082        │   0.082        │   0.082        │   0.146   │ 1            │            │            │
├───────────────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┼───────────┼─────────┼─────────┼─────────┼─────────┼────────────────┼────────────────┼────────────────┼───────────┼──────────────┼────────────┼────────────┤
│ Sum                       │   0.299  │   0.299 │   0.299 │   0.299 │   0.297 │   0.299   │   0.000 │   0.068 │   0.068 │   0.068 │   0.161        │   0.161        │   0.162        │   0.367   │ 3            │            │            │
├───────────────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┼───────────┼─────────┼─────────┼─────────┼─────────┼────────────────┼────────────────┼────────────────┼───────────┼──────────────┼────────────┼────────────┤
│ Avg                       │   0.100  │   0.100 │   0.100 │   0.100 │   0.099 │   0.100   │   0.000 │   0.023 │   0.023 │   0.023 │   0.054        │   0.054        │   0.054        │   0.122   │ 3            │            │            │
├───────────────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┼───────────┼─────────┼─────────┼─────────┼─────────┼────────────────┼────────────────┼────────────────┼───────────┼──────────────┼────────────┼────────────┤
│ GAvg                      │   0.097  │   0.097 │   0.097 │   0.097 │   0.097 │   0.097   │   0.000 │   0.018 │   0.018 │   0.001 │   0.051        │   0.051        │   0.001        │   0.000   │ 3            │            │            │
└───────────────────────────┴──────────┴─────────┴─────────┴─────────┴─────────┴───────────┴─────────┴─────────┴─────────┴─────────┴────────────────┴────────────────┴────────────────┴───────────┴──────────────┴────────────┴────────────┘

Results saved to results.out

Очистите таблицы

ydb workload query --path user_path clean