libfpta - обгоняя
SQLite и Tarantool
Леонид Юрьев
Advanced Research @ Positive Technologies
Алексей Копытов
Эксперт @ Голос Разума
Обогнали!
Увидимся на «Хабре»
https://github.com/PositiveTechnologies/libfpta
https://github.com/PositiveTechnologies/libfptu
https://github.com/leo-yuriev/libmdbx
libfpta
libfpta:
– в памяти
– с персистентностью
– быстрее хайпа
Леонид Юрьев
Advanced Research @ Positive Technologies
Алексей Копытов
Эксперт @ Голос Разума
Потребовалось
оперативное хранилище
– очень быстрое
– для локальных процессов
– без излишеств, но развиваемое…
Взяли и сделали.
libfpta: Постановка задачи
Локально, DATA < RAM
– один нагруженный сервер
– несколько читателей и 2-3 процесса-писателя
Быстро
– если медленно, то не нужно
Долговечность иногда не важна
– при аварии питания данные устаревают
Высокая готовность
– минимальное время восстановления
– падение не должно ломать или прятать данные
Позитивные таблицы
1. Обзор
2. Варианты использования: Целевой и Неправильный
3. Плюсы
4. Минусы
5. Планы
6. Чем не устроили: Ignite, Tarantool, SQLite, RocksDB…
libfpta – Движок хранения
Компактная библиотека с лицензией LGPL
libfpta = libmdbx (key-value) + libfptu (tuples) + t1ha (hash)
Таблицы с «утиной» схемой, всяческие индексы
Экстремально быстрый, но без WAL (пока)
Похожий, но Иной
libfpta: 80% как у всех
1. Набор таблиц с колонкам и индексами
2. Машинные типы, дата-время, строки, NULL…
3. Курсоры
4. BREAD
5. Рой процессов
6. Пока отсутствуют: FOREIGN KEYs, JOINs
Внутри транзакций
чтения/записи
libfpta: Внутри
Данные отображены в RAM
– B+Tree, не LSM
– ACID* поверх MVCC
– MVCC посредством COW на уровне страниц
Key-value, кортежи, список таблиц, список колонок…
– нет имен, только дайджесты t1ha
Предельно эффективно для машины
– считаем кэш-линии и такты
– ничего лишнего или неэффективного
libfpta: Не подойдет
Много «апдейтов» и
– нельзя потерять при аварии питания
– допустим простой при восстановлении
= показан WAL
READ < WRITE && RAM < DATA
= показан LSM
libfpta: Идеально
Требуется предельная производительность
– ACID для локальной группы процессов
– с выборкой диапазонов и курсорами
Не нужен WAL
– требуется минимальное время простоя
– допустимо потерять «хвост» при аварии
( при kill -9 ничего не потеряется )
– диск терпит WAF от апдейтов
READ > WRITE || RAM > DATA
– иначе LSM даст больше
libfpta: Скорость
READ / GET
𝑂 log(𝑁) = поиск в B+tree
Как std::map или чуть
быстрее (за счет локальности)
На каждом CPU
без блокировок в БД
Подкачка если DATA > RAM
WRITE / UPSERT
𝑂 log(𝑁) = Изменение B+tree
Копирование страниц по
высоте дерева
Транзакции строго
последовательны
Фиксация на диске
MDBX
RocksDB
READ4threads SYNC LAZY
libfpta: Попугаи
MDBX
RocksDB
I/O SPACECPU
Производительность
Стоимость
libfpta: «Утиная» схема
Записи являются кортежами
Схема задает минимальный набор
Полей может быть больше…
Для «лишних» полей
– машинный тип
– числовой тэг (до 1000)
– будет: справочник схемы
Дополнительные
полу-структурированные
данные
libfpta: Кортежи
Реализованы в libfptu:
– похожи на BSON и MessagePack
– без сжатия
– поддерживаются коллекции (repeated в ProtoBuf)
– в заголовке есть «индекс»
– предельно удобны для машины
– подключаемый словарь схемы (будет, вместе с JSON)
– могут быть вложенным
– предусмотрены массивы
libfpta: Дубликаты
Дубликаты – это multi-value
– во вложенных деревьях
– ключи не дублируются
– значения отсортированы
– курсоры могут ходить по «дубликатам»
– быстрый поиск и позиционирование
libfpta: Конкуренция
Один писатель
– Один разделяемый мьютекс (1)
– Изменения всегда последовательны
Много читателей
– Подключение/отключение под вторым мьютексом (2)
– Выполнение без блокировок внутри БД
Временно
– Изменение схемы под мьютексом внутри процесса (3)
libfpta: Индексы
Составные
– по совокупному значению колонок
Неупорядоченные
– хэши t1ha вместо значений, требуют меньше места
Реверсивные
– ключи сравниваются с конца, хорошо для доменов
Функциональные / Пользовательские (обдумываем)
– как генераторы ключей, не компараторы
– collate/uppercase
libfpta: Немного деталей
Первичный индекс есть всегда
Нет RowID
– есть последовательности
– будет auto (эмуляция RowID)
Вторичные индекс через PK
– как в MySQL, НЕ как в PostgreSQL
– требуют уникальности PK
libfpta: Не как у людей…
Контроль уникальности
– это атрибут индекса
NULL в индексах
– заменяется на Designated NIL
– проверяется на уникальность
Триггеры
– пока не хотим, нет «сервера»
Пока отсутствуют
– Collate и Case Insensitive
– FOREIGN KEYs
– JOINs
– OPTIMIZER / REWRITER
Пока не требовалось,
но будет…
libfpta: Недостатки
Отсутствие WAL
– требует смены формата
Проблема долгих чтений
– требует большого рефакторинга
Наследство от LMDB
Были причины не трогать
Будем устранять
libfpta: WAL или NO-WAL?
Без WAL
– Большой WAF
– Медленно на HDD
+ Моментальная готовность
Тем не менее
+ OOM и kill = не проблема
+ есть LIFO для BBWC
Нам было достаточно,
но WAL скоро будет
+ Небольшой WAF
+ Быстрее на HDD
± sync/flush (всё-таки нужен…)
– Replay после аварии
libfpta: Планы и хотелки
libmdbx (key-value):
– Новое API
– Рефакторинг…
– Асинхронная фиксация
– Merkle Tree
– WAL
– Другая «сборка мусора»
– Вынос span-pages и
поддержка RAW-устройств
(Nexenta Edge)
libfptu (кортежи):
– поддержка справочника схемы
– (де)сериализация в JSON
– (де)сериализация в MsgPack
libfpta (всё вместе):
– поддержка python…
– «оптимизатор» запросов
– FK, JOIN, GIN…
libfpta: Трудности
KISS
– взвешенный аскетизм, не переинженерить, меньше ребусов
Тесты
– комбинаторная сложность
– оркестр процессов
– поведенческие паттерны
Люди
– ищем в команду
Apache Ignite?
Java = неустранимые накладные расходы
– не для предельной производительности
libfpta:
1) Не нужна распределённость
2) Не делает лишнего
3) В несколько раз быстрее
Tarantool, Aerospike, etc…?
Сеть = неустранимые накладные расходы
– системные вызовы, маршалинг, event loop
libfpta:
1) Чтение линейно масштабируется по CPU
2) Чтение без блокировок, непосредственно из RAM
3) Интегрально в несколько раз быстрее*
SQLite, RocksDB…?
Одна БД = Один процесс

libfpta:
1) Рой локальных процессов
2) Два разделяемых мьютекса
3) В несколько раз быстрее
Спасибо!
Увидимся на «Хабре»
https://github.com/PositiveTechnologies/libfpta
https://github.com/PositiveTechnologies/libfptu
https://github.com/leo-yuriev/libmdbx
libfpta

libfpta — обгоняя SQLite и Tarantool / Леонид Юрьев (Positive Technologies)

  • 1.
    libfpta - обгоняя SQLiteи Tarantool Леонид Юрьев Advanced Research @ Positive Technologies Алексей Копытов Эксперт @ Голос Разума
  • 2.
  • 3.
    libfpta: – в памяти –с персистентностью – быстрее хайпа Леонид Юрьев Advanced Research @ Positive Technologies Алексей Копытов Эксперт @ Голос Разума
  • 4.
    Потребовалось оперативное хранилище – оченьбыстрое – для локальных процессов – без излишеств, но развиваемое… Взяли и сделали.
  • 5.
    libfpta: Постановка задачи Локально,DATA < RAM – один нагруженный сервер – несколько читателей и 2-3 процесса-писателя Быстро – если медленно, то не нужно Долговечность иногда не важна – при аварии питания данные устаревают Высокая готовность – минимальное время восстановления – падение не должно ломать или прятать данные
  • 6.
    Позитивные таблицы 1. Обзор 2.Варианты использования: Целевой и Неправильный 3. Плюсы 4. Минусы 5. Планы 6. Чем не устроили: Ignite, Tarantool, SQLite, RocksDB…
  • 7.
    libfpta – Движокхранения Компактная библиотека с лицензией LGPL libfpta = libmdbx (key-value) + libfptu (tuples) + t1ha (hash) Таблицы с «утиной» схемой, всяческие индексы Экстремально быстрый, но без WAL (пока) Похожий, но Иной
  • 8.
    libfpta: 80% каку всех 1. Набор таблиц с колонкам и индексами 2. Машинные типы, дата-время, строки, NULL… 3. Курсоры 4. BREAD 5. Рой процессов 6. Пока отсутствуют: FOREIGN KEYs, JOINs Внутри транзакций чтения/записи
  • 9.
    libfpta: Внутри Данные отображеныв RAM – B+Tree, не LSM – ACID* поверх MVCC – MVCC посредством COW на уровне страниц Key-value, кортежи, список таблиц, список колонок… – нет имен, только дайджесты t1ha Предельно эффективно для машины – считаем кэш-линии и такты – ничего лишнего или неэффективного
  • 10.
    libfpta: Не подойдет Много«апдейтов» и – нельзя потерять при аварии питания – допустим простой при восстановлении = показан WAL READ < WRITE && RAM < DATA = показан LSM
  • 11.
    libfpta: Идеально Требуется предельнаяпроизводительность – ACID для локальной группы процессов – с выборкой диапазонов и курсорами Не нужен WAL – требуется минимальное время простоя – допустимо потерять «хвост» при аварии ( при kill -9 ничего не потеряется ) – диск терпит WAF от апдейтов READ > WRITE || RAM > DATA – иначе LSM даст больше
  • 12.
    libfpta: Скорость READ /GET 𝑂 log(𝑁) = поиск в B+tree Как std::map или чуть быстрее (за счет локальности) На каждом CPU без блокировок в БД Подкачка если DATA > RAM WRITE / UPSERT 𝑂 log(𝑁) = Изменение B+tree Копирование страниц по высоте дерева Транзакции строго последовательны Фиксация на диске
  • 13.
    MDBX RocksDB READ4threads SYNC LAZY libfpta:Попугаи MDBX RocksDB I/O SPACECPU Производительность Стоимость
  • 14.
    libfpta: «Утиная» схема Записиявляются кортежами Схема задает минимальный набор Полей может быть больше… Для «лишних» полей – машинный тип – числовой тэг (до 1000) – будет: справочник схемы Дополнительные полу-структурированные данные
  • 15.
    libfpta: Кортежи Реализованы вlibfptu: – похожи на BSON и MessagePack – без сжатия – поддерживаются коллекции (repeated в ProtoBuf) – в заголовке есть «индекс» – предельно удобны для машины – подключаемый словарь схемы (будет, вместе с JSON) – могут быть вложенным – предусмотрены массивы
  • 16.
    libfpta: Дубликаты Дубликаты –это multi-value – во вложенных деревьях – ключи не дублируются – значения отсортированы – курсоры могут ходить по «дубликатам» – быстрый поиск и позиционирование
  • 17.
    libfpta: Конкуренция Один писатель –Один разделяемый мьютекс (1) – Изменения всегда последовательны Много читателей – Подключение/отключение под вторым мьютексом (2) – Выполнение без блокировок внутри БД Временно – Изменение схемы под мьютексом внутри процесса (3)
  • 18.
    libfpta: Индексы Составные – посовокупному значению колонок Неупорядоченные – хэши t1ha вместо значений, требуют меньше места Реверсивные – ключи сравниваются с конца, хорошо для доменов Функциональные / Пользовательские (обдумываем) – как генераторы ключей, не компараторы – collate/uppercase
  • 19.
    libfpta: Немного деталей Первичныйиндекс есть всегда Нет RowID – есть последовательности – будет auto (эмуляция RowID) Вторичные индекс через PK – как в MySQL, НЕ как в PostgreSQL – требуют уникальности PK
  • 20.
    libfpta: Не каку людей… Контроль уникальности – это атрибут индекса NULL в индексах – заменяется на Designated NIL – проверяется на уникальность Триггеры – пока не хотим, нет «сервера» Пока отсутствуют – Collate и Case Insensitive – FOREIGN KEYs – JOINs – OPTIMIZER / REWRITER Пока не требовалось, но будет…
  • 21.
    libfpta: Недостатки Отсутствие WAL –требует смены формата Проблема долгих чтений – требует большого рефакторинга Наследство от LMDB Были причины не трогать Будем устранять
  • 22.
    libfpta: WAL илиNO-WAL? Без WAL – Большой WAF – Медленно на HDD + Моментальная готовность Тем не менее + OOM и kill = не проблема + есть LIFO для BBWC Нам было достаточно, но WAL скоро будет + Небольшой WAF + Быстрее на HDD ± sync/flush (всё-таки нужен…) – Replay после аварии
  • 23.
    libfpta: Планы ихотелки libmdbx (key-value): – Новое API – Рефакторинг… – Асинхронная фиксация – Merkle Tree – WAL – Другая «сборка мусора» – Вынос span-pages и поддержка RAW-устройств (Nexenta Edge) libfptu (кортежи): – поддержка справочника схемы – (де)сериализация в JSON – (де)сериализация в MsgPack libfpta (всё вместе): – поддержка python… – «оптимизатор» запросов – FK, JOIN, GIN…
  • 24.
    libfpta: Трудности KISS – взвешенныйаскетизм, не переинженерить, меньше ребусов Тесты – комбинаторная сложность – оркестр процессов – поведенческие паттерны Люди – ищем в команду
  • 25.
    Apache Ignite? Java =неустранимые накладные расходы – не для предельной производительности libfpta: 1) Не нужна распределённость 2) Не делает лишнего 3) В несколько раз быстрее
  • 26.
    Tarantool, Aerospike, etc…? Сеть= неустранимые накладные расходы – системные вызовы, маршалинг, event loop libfpta: 1) Чтение линейно масштабируется по CPU 2) Чтение без блокировок, непосредственно из RAM 3) Интегрально в несколько раз быстрее*
  • 27.
    SQLite, RocksDB…? Одна БД= Один процесс  libfpta: 1) Рой локальных процессов 2) Два разделяемых мьютекса 3) В несколько раз быстрее
  • 28.