Нагрузочное тестирование плагина Sirin для СУБД Picodata

Sirin — плагин для Picodata, реализующий протокол Apache Cassandra. Мы сравнили его производительность с Cassandra 5.0.6 на timeseries-нагрузке: запись строк двух размеров, точечное и пакетное чтение. Оба стенда ограничены 6 ядрами CPU, используется конфигурация СУБД по умолчанию.

ТестSirin, RPSCassandra, RPSОтношение
Запись 30 байт190 198197 165Cassandra ×1.04
Запись 150 байт147 416186 739Cassandra ×1.27
Пакетное чтение (5 000 строк)468603Cassandra ×1.29
Точечное чтение166 14318 750Sirin ×8.9

Введение

Sirin — плагин для распределённой СУБД Picodata, реализующий протокол Apache Cassandra. Благодаря этому плагину приложения, использующие драйверы CQL, могут работать с Picodata без изменения кода.

Целью данного документа является оценка производительности Sirin в сравнении с Cassandra 5.0.6 — эталонной реализацией протокола. Сравнение позволяет определить, насколько Sirin пригоден для замены Cassandra в типовых сценариях нагрузки, а также выявить области, требующие дальнейшей оптимизации.

Тестирование охватывает операции записи и чтения на схеме данных, характерной для timeseries workload. Измеряются пропускная способность, время выполнения запросов, потребление вычислительных ресурсов (CPU, RAM) и нагрузка на дисковую подсистему.

Условия

Стенд

Базы данных и генератор нагрузки запускались на отдельных виртуальных машинах и взаимодействовали через сеть, что исключало конкуренцию за ресурсы между тестируемой БД и инструментом нагрузки.

Конфигурация ВМ с базами данных:

РесурсЗначение
CPU8 ядер
RAM16 ГБ
Диск200 ГБ NVMe SSD

Конфигурация баз данных

Обе системы тестировались без репликации данных. Лимит CPU в 6 ядер задавался через cgroups одинаково для обеих систем, чтобы обеспечить сравнимые условия.

СистемаТопология
Cassandra 5.0.6Один процесс, обслуживающий все запросы
Sirin 1.0.2 на Picodata 26.1.1Кластер из 5 узлов на одной машине

Схема данных

Использовалась типовая схема данных для timeseries-нагрузки:

CREATE TABLE ${KEYSPACE}.${TABLE}(
    partition_key  text,
    clustering_key timeuuid,
    data           blob,
    PRIMARY KEY ((partition_key), clustering_key)
)

Входные данные

Исходный размер одной строки “сырых” данных, используемых в тестах:

Запись полезной нагрузки в 30 байт в 10 000 партиций:

ПолеТипРазмер
partition_keytext18 байт
clustering_keytimeuuid16 байт
datablob30 байт
Итого64 байта

Запись полезной нагрузки в 150 байт в 10 000 партиций:

ПолеТипРазмер
partition_keytext18 байт
clustering_keytimeuuid16 байт
datablob150 байт
Итого184 байта

Используемый инструмент

Тесты проводились утилитой latte.

Набор тестов

ТестОписание
Запись полезной нагрузки в 30 байт в 10 000 партицийЗапись одной строки (64 байта) в случайную из 10 000 партиций
Запись полезной нагрузки в 150 байт в 10 000 партицийЗапись одной строки (184 байта) в случайную из 10 000 партиций
Точечное чтениеЧтение одного объекта из 10 000 партиций
Пакетное чтениеЧтение 5 000 объектов из 10 000 партиций

Объём тестовых данных

Тесты чтения проводились на данных, накопленных в ходе теста «Запись 30 байт». Тест «Запись 150 байт» генерировал собственный независимый набор данных.

ТестСистемаЧисло строкОбъём сырых данных
Запись полезной нагрузки в 30 байт в 10 000 партицийSirin684 715 98540.8 ГБ
Запись полезной нагрузки в 30 байт в 10 000 партицийCassandra709 796 02842.3 ГБ
Запись полезной нагрузки в 150 байт в 10 000 партицийSirin530 700 06190.9 ГБ
Запись полезной нагрузки в 150 байт в 10 000 партицийCassandra672 261 629115.2 ГБ

Объём сырых данных рассчитан как произведение числа строк на размер одной строки (64 и 184 байта соответственно).

Измеряемые параметры

КатегорияПараметры
Пропускная способностьЗапросов в секунду (RPS)
Время выполнения запросовМедиана, p90, p95 времени выполнения запроса
CPUСуммарное потребление по всем процессам БД
RAMСуммарное потребление по всем процессам БД
ДискIOPS и пропускная способность (МБ/с) на чтение и запись
Write amplificationМножитель суммарной записи на диск относительно объёма сырых данных

Результаты

Запись полезной нагрузки в 30 байт в 10000 партиций

Команда для запуска теста:

latte run write.rn 192.168.1.103:9042 --duration 60m -p 60 --threads 16 --connections 100

Запрос (prepared statement):

INSERT INTO latte.basic (partition_key, clustering_key, data)
VALUES (:pk, :ck, :data)

Значение partition_key выбирается равномерно из 10 000 партиций, clustering_key — timeuuid, data — blob фиксированного размера.

ПараметрSirinCassandra
Пропускная способность, RPS190 198197 165
Время выполнения p90, мс10.61712.05
Время выполнения p95, мс14.67218.02
Время выполнения медиана, мс3.4322.55
Потребление CPU, %~8086
Потребление RAM, ГБ4.05.7
Макс. запись на диск, IOPS45075
Макс. чтение с диска, IOPS103162
Макс. запись на диск, МБ/с92.6165.02
Макс. чтение с диска, МБ/с61.1326.35
Write amplification3.754.42
Записано объектов684 715 985709 796 028
Объём сырых данных, ГБ40.842.3
Телеметрия — Sirin

Пропускная способностьПропускная способность (RPS) в течение теста — график latte

ЗадержкаВремя выполнения запроса: p50, p90, p95 (мс) — график latte

CPUЗагрузка CPU (%) по узлам кластера в течение теста

RAMПотребление оперативной памяти (ГБ) по узлам кластера в течение теста

Дисковая активность — IOPSДисковая активность: IOPS на запись и чтение

Дисковая активность — пропускная способностьДисковая активность: пропускная способность (МБ/с) на запись и чтение

Суммарный объём ввода-выводаСуммарный объём данных, записанных и прочитанных с диска за время теста (байт)

СетьУтилизация сетевого канала: входящий и исходящий трафик (МБ/с)

Телеметрия — Cassandra

Пропускная способностьПропускная способность (RPS) в течение теста — график latte

ЗадержкаВремя выполнения запроса: p50, p90, p95 (мс) — график latte

CPUЗагрузка CPU (%) в течение теста

RAMПотребление оперативной памяти (ГБ) в течение теста

Дисковая активность — IOPSДисковая активность: IOPS на запись и чтение

Дисковая активность — пропускная способностьДисковая активность: пропускная способность (МБ/с) на запись и чтение

Суммарный объём ввода-выводаСуммарный объём данных, записанных и прочитанных с диска за время теста (байт)

СетьУтилизация сетевого канала: входящий и исходящий трафик (МБ/с)

Запись полезной нагрузки в 150 байт в 10 000 партиций

Команда для запуска теста:

latte run write.rn 192.168.1.103:9042 --duration 60m -p 60 --threads 16 --connections 100

Запрос (prepared statement):

INSERT INTO latte.basic (partition_key, clustering_key, data)
VALUES (:pk, :ck, :data)

Значение partition_key выбирается равномерно из 10 000 партиций, clustering_key — timeuuid, data — blob фиксированного размера.

ПараметрSirinCassandra
Пропускная способность, RPS147416186739
Время выполнения p90, мс16.0712.89
Время выполнения p95, мс22.6418.55
Время выполнения медиана, мс3.532.71
Потребление CPU, %8788
Потребление RAM, ГБ5.16.08
Макс. запись на диск, IOPS251162.2
Макс. чтение с диска, IOPS1230395
Макс. запись на диск, МБ/с220.5149.7
Макс. чтение с диска, МБ/с160.268.1
Write amplification4.635.09
Записано объектов530 700 061672 261 629
Объём сырых данных, ГБ90.9115.2
Телеметрия — Sirin

Пропускная способностьПропускная способность (RPS) в течение теста — график latte

ЗадержкаВремя выполнения запроса: p50, p90, p95 (мс) — график latte

CPUЗагрузка CPU (%) по узлам кластера в течение теста

RAMПотребление оперативной памяти (ГБ) по узлам кластера в течение теста

Дисковая активность — IOPSДисковая активность: IOPS на запись и чтение

Дисковая активность — пропускная способностьДисковая активность: пропускная способность (МБ/с) на запись и чтение

Суммарный объём ввода-выводаСуммарный объём данных, записанных и прочитанных с диска за время теста (байт)

СетьУтилизация сетевого канала: входящий и исходящий трафик (МБ/с)

Телеметрия — Cassandra

Пропускная способностьПропускная способность (RPS) в течение теста — график latte

ЗадержкаВремя выполнения запроса: p50, p90, p95 (мс) — график latte

CPUЗагрузка CPU (%) в течение теста

RAMПотребление оперативной памяти (ГБ) в течение теста

Дисковая активность — IOPSДисковая активность: IOPS на запись и чтение

Дисковая активность — пропускная способностьДисковая активность: пропускная способность (МБ/с) на запись и чтение

Суммарный объём ввода-выводаСуммарный объём данных, записанных и прочитанных с диска за время теста (байт)

СетьУтилизация сетевого канала: входящий и исходящий трафик (МБ/с)

Пакетное чтение по 5000 объектов из 10 000 партиций

Команда для запуска теста:

latte run read_batch.rn 192.168.1.103:9042 --duration 60m -p 10 --threads 3 --connections 20

Запрос (prepared statement):

SELECT * FROM latte.basic
WHERE partition_key = :pk AND clustering_key > :ck
LIMIT 5000

Читается до 5 000 строк из случайной партиции начиная со случайного clustering_key.

ПараметрSirinCassandra
Пропускная способность, RPS494603
Время выполнения p90, мс11987.6
Время выполнения p95, мс155100
Время выполнения медиана, мс47.244.8
Потребление CPU, %6778
Потребление RAM, ГБ2.55.85
Макс. чтение с диска, KIOPS3.3111.10
Макс. чтение с диска, МБ/с148.11279.8
Read amplification1.071.3
Телеметрия — Sirin

Пропускная способностьПропускная способность (RPS) в течение теста — график latte

ЗадержкаВремя выполнения запроса: p50, p90, p95 (мс) — график latte

CPUЗагрузка CPU (%) по узлам кластера в течение теста

RAMПотребление оперативной памяти (ГБ) по узлам кластера в течение теста

Дисковая активность — IOPSДисковая активность: IOPS на чтение

Дисковая активность — пропускная способностьДисковая активность: пропускная способность (МБ/с) на чтение

Суммарный объём ввода-выводаСуммарный объём данных, прочитанных с диска за время теста (байт)

СетьУтилизация сетевого канала: входящий и исходящий трафик (МБ/с)

Телеметрия — Cassandra

Пропускная способностьПропускная способность (RPS) в течение теста — график latte

ЗадержкаВремя выполнения запроса: p50, p90, p95 (мс) — график latte

CPUЗагрузка CPU (%) в течение теста

RAMПотребление оперативной памяти (ГБ) в течение теста

Дисковая активность — IOPSДисковая активность: IOPS на чтение

Дисковая активность — пропускная способностьДисковая активность: пропускная способность (МБ/с) на чтение

Суммарный объём ввода-выводаСуммарный объём данных, прочитанных с диска за время теста (байт)

СетьУтилизация сетевого канала: входящий и исходящий трафик (МБ/с)

Точечное чтение из 10 000 партиций

Команда для запуска теста:

latte run read_single.rn 192.168.1.103:9042 --duration 60m -p 60 --threads 16 --connections 100

Запрос (prepared statement):

SELECT * FROM latte.basic
WHERE partition_key = :pk AND clustering_key = :ck

Читается ровно одна строка по точному значению partition_key и clustering_key.

ПараметрSirinCassandra
Пропускная способность, RPS166 14318 750
Время выполнения p90, мс14.1359.28
Время выполнения p95, мс20.6161.51
Время выполнения медиана, мс2.8851.71
Потребление CPU, %~9389
Потребление RAM, ГБ4.05.77
Макс. чтение с диска, KIOPS5.771.7
Макс. чтение с диска, МБ/с155.411 530
Read amplification15.211 356
Телеметрия — Sirin

Пропускная способностьПропускная способность (RPS) в течение теста — график latte

ЗадержкаВремя выполнения запроса: p50, p90, p95 (мс) — график latte

CPUЗагрузка CPU (%) по узлам кластера в течение теста

RAMПотребление оперативной памяти (ГБ) по узлам кластера в течение теста

Дисковая активность — IOPSДисковая активность: IOPS на чтение

Дисковая активность — пропускная способностьДисковая активность: пропускная способность (МБ/с) на чтение

Суммарный объём ввода-выводаСуммарный объём данных, прочитанных с диска за время теста (байт)

СетьУтилизация сетевого канала: входящий и исходящий трафик (МБ/с)

Телеметрия — Cassandra

Пропускная способностьПропускная способность (RPS) в течение теста — график latte

ЗадержкаВремя выполнения запроса: p50, p90, p95 (мс) — график latte

CPUЗагрузка CPU (%) в течение теста

RAMПотребление оперативной памяти (ГБ) в течение теста

Дисковая активность — IOPSДисковая активность: IOPS на чтение

Дисковая активность — пропускная способностьДисковая активность: пропускная способность (МБ/с) на чтение

Суммарный объём ввода-выводаСуммарный объём данных, прочитанных с диска за время теста (байт)

СетьУтилизация сетевого канала: входящий и исходящий трафик (МБ/с)

Выводы

Архитектурный контекст

Picodata обрабатывает запросы в одном вычислительном потоке на узел (event loop), отдельно от IO-потоков движка Vinyl. При конфигурации в 5 узлов на 6 ядрах это даёт архитектурный потолок по compute-нагрузке в 5/6 ≈ 83% суммарного CPU. Cassandra, напротив, использует пул потоков и задействует все доступные ядра.

Для корректного сравнения ниже приведена нормализованная эффективность — RPS на 1% потреблённого CPU:

ТестSirin, RPS/%Cassandra, RPS/%Отношение
Запись полезной нагрузки в 30 байт в 10 000 партиций2 3772 293Sirin ×1.04
Запись полезной нагрузки в 150 байт в 10 000 партиций1 6942 122Cassandra ×1.25
Пакетное чтение по 5000 объектов из 10 000 партиций7.27.7Cassandra ×1.07
Точечное чтение из 10 000 партиций1 786211Sirin ×8.5

Запись полезной нагрузки в 30 байт

Пропускная способность сопоставима: различие Sirin Cassandra в скорости (190 198 против 197 165 RPS), сопоставимо со снижением затрат по CPU (80% против 86%). По нормализованной эффективности Sirin незначительно превосходит Cassandra (+3.7%).

Хвостовые задержки (tail latency) у Sirin лучше (p90: 10.6 мс против 12.1 мс, p95: 14.7 мс против 18.0 мс), медиана выше (3.4 мс против 2.6 мс). Sirin потребляет меньше RAM (4.0 против 5.7 ГБ) и демонстрирует меньший write amplification (3.75 против 4.42).

Запись полезной нагрузки в 150 байт

При увеличении полезной нагрузки с 30 до 150 байт Sirin выдаёт 147 416 RPS при CPU ~87% — столько же, что у Cassandra. Cassandra при аналогичном CPU достигает 186 739 RPS.

Дисковая активность при 150-байтной нагрузке выше, чем в 30-байтном тесте: пиковое чтение с диска достигает 1 230 IOPS и 160 МБ/с против 103 IOPS и 61 МБ/с, что отражает активное слияние уровней LSM-дерева Vinyl во время теста.

Write amplification у Sirin несколько выше, чем в 30-байтном тесте (4.63 против 3.75); у Cassandra аналогичная динамика (5.09 против 4.42). Следует учитывать, что процесс компакции у Cassandra продолжается в фоне как во время теста, так и после его окончания.

Пакетное чтение

В абсолютных числах Sirin выдаёт 468 RPS против 603 у Cassandra. При нормализации по CPU разрыв сокращается до 7%: Sirin работает при 65% CPU, тогда как Cassandra — при 78%. Запас по CPU у Sirin объясняется ограничением на число одновременно обрабатываемых запросов, обусловленным однопоточной моделью Picodata.

Read amplification у Sirin ниже (1.07 против 1.3), нагрузка на диск меньше.

Точечное чтение

Наиболее показательный сценарий. Sirin опережает Cassandra в 8.9 раза по абсолютной пропускной способности (166 143 против 18 750 RPS) и в 8.5 раза по CPU-нормализованной эффективности. При этом Sirin работает на 93% CPU, превышая compute-потолок — разница покрывается IO-потоками Vinyl, которые обслуживают операции чтения параллельно.

Главная причина отрыва — разница в read amplification: 15.21 у Sirin против 1 356 у Cassandra. При точечных запросах Cassandra вынуждена читать с диска в 90 раз больше данных, что упирает её производительность в пропускную способность дисковой подсистемы.

Разница объясняется различиями в стратегии слияний LSM-дерева и коррелирует с различиями в производительности записи: стратегия Vinyl в поиске баланса скорости чтения и скорости записи, поэтому объём выполняемой работы во время записи выше. Cassandra использует свою стратегию слияний по умолчанию (STCS).

Потребление ресурсов

Потребление RAM у Sirin стабильно во всех тестах — ~4.0–5.1 ГБ в зависимости от размера строк, тогда как у Cassandra 5.7–6.1 ГБ.

Итог

По CPU-нормализованной эффективности Sirin сопоставим с Cassandra на записи малых строк и кратно превосходит на точечном чтении. На записи 150-байтных строк Cassandra опережает Sirin по эффективности в 1.25 раза: более крупные строки усиливают конкуренцию между компакцией Vinyl и обработкой запросов. На пакетном чтении обе системы практически равны с небольшим преимуществом Cassandra