Архитектура хранения¶
Tarantool Column Store – колоночная транзакционно-аналитическая СУБД, построенная на платформе Tarantool Enterprise Edition. TCS наследует от Tarantool базовые возможности хранения и масштабирования:
данные хранятся в оперативной памяти;
хранение персистентно;
доступен механизм репликации.
TCS относится к гибридному классу систем хранения HTAP (Hybrid transactional/analytical processing): основное хранилище использует колоночно-ориентированный формат, а буфер, в который поступают новые объекты при записи – либо также колоночный, либо традиционный строчный формат. Такая архитектура позволяет добиться оптимальной производительности аналитических запросов (OLAP) наряду с характерной для Tarantool высокой производительностью при транзакционной нагрузке (OLTP).
Хранение данных в TCS организовано следующим образом:
Далее объясняются детали реализации основных механизмов TCS:
Колоночное хранение¶
Основное хранилище данных TCS имеет колоночный формат.
Ключевое отличие колоночных СУБД от реляционных СУБД с табличным хранением – использование колонки в качестве единицы хранения вместо таблицы. В реляционной СУБД все поля одного объекта хранятся рядом в виде одной строки таблицы. В свою очередь, в колоночной рядом располагаются все значения одного поля таблицы, а поля одного объекта разнесены по соответствующим колонкам и не хранятся вместе.
Использование колоночного формата позволяет оптимизировать работу TCS под нагрузкой, характерной для аналитических задач (OLAP), то есть при большом количестве запросов на чтение и вычисление агрегатов.
Буферы записи¶
В отличие от запросов на чтение, вставка объектов в колоночных СУБД обычно менее производительна, чем в реляционных. Это связано с тем, что при каждой вставке объект нужно разделить на поля и вставить значение каждого поля в свою область памяти, которая хранит соответствующую колонку.
Для решения этой проблемы TCS использует два формата буферизации записи: строчный и колоночный. Запись в буфер осуществляется с использованием соответствующего движка обработки данных в Tarantool:
движок MemTX для строчного формата,
движок MemCS для колоночного формата.
Это обеспечивает высокую производительность TCS под транзакционной нагрузкой (OLTP).
Вид буферизации для каждой таблицы задается в конфигурации. По умолчанию используется строчная буферизация.
Новые объекты записываются в соответствующий буфер, где они хранятся в формате обычной таблицы СУБД, построчно или поколоночно. При заполнении буфера до размера блока хранения все данные из него переносятся за один раз в основное колоночное хранилище. После этого буфер очищается.
Схема работы строчного буфера:
Схема работы колоночного буфера:
Примечание
Наилучшая производительность достигается при вставке объектов пачками, совпадающими по размеру с размером буфера.
Блоки хранения¶
В TCS значения каждой колонки разделены на блоки одинакового размера. Размер одного блока - 8192 значения. Это число выбрано как оптимальное с точки зрения использования вычислительных ресурсов.
Такая реализация позволяет улучшить производительность операций вставки и удаления данных. При добавлении новых объектов они собираются в буфер и перемещаются в основное колоночное хранилище, когда он заполняется. Размер буфера равен размеру блока. Таким образом, вместо множественных вставок в колоночное хранилище выполняется однократное добавление блока для каждой колонки.
Аналогично работает вытеснение данных из хранилища: вместо удаления каждого объекта выполняется удаление целого блока, когда все его значения выходят за предел хранения.
Чтение данных¶
Как гибридное решение, TCS предполагает работу под транзакционной нагрузкой на запись. Для консистентности чтения данных в таких условиях TCS использует представления для чтения (read view) – снимки хранилища данных в конкретный момент времени.
В каждый момент времени в TCS существует одно актуальное представление на чтение.
Оно обновляется раз в .aggregator.rv_update_ms миллисекунд. Когда приходит запрос
на чтение данных, для него используется актуальное представление.
Важно
Чтение данных реализовано так, что значения в буфере также учитываются при выполнении запроса.
Чтение выполняется в многопоточном режиме. Каждый поток, выполняющий запрос на чтение,
использует свое представление. В системе хранится набор всех используемых в данный момент
представлений, то есть тех, из которых еще выполняется чтение в рамках выполнения запросов.
Когда обработка запроса завершена, и при этом уже создано более актуальное представление,
то представление, которые использовалось для этого запроса, помещается в очередь
на удаление. Представления из этой очереди удаляются при следующей итерации цикла
сборщика мусора (раз в .aggregator.rv_update_ms миллисекунд).
Подробнее о представлениях на чтение читайте в документации Tarantool EE.
Вытеснение данных¶
Удаление данных из TCS выполняется автоматически по мере заполнения хранилища. Такой механизм также известен как вытеснение. При добавлении новых объектов сверх лимита одновременно хранимых данных наиболее старые данные удаляются.
В TCS вытеснение организовано поколоночно: для каждой колонки может быть определен
свой лимит количества одновременно хранимых значений. Лимиты задаются в модели данных
в атрибутах default_column_values_limit (по умолчанию для всех существующих колонок)
или column_values_limit (для отдельной колонки).
Важно
При установке значения column_values_limit для колонки необходимо учитывать сценарии
использования этой колонки в запросах. Например, если в таблице хранится
10 000 значений одной колонки и 100 000 значений другой колонки, то получить целиком
из этой таблицы можно только 10 000 последних объектов.
Вытеснение значений производится блоками: например, если в колонке уже хранится предельное количество значений, то вставка одного нового значения не приводит к немедленному удалению одного наиболее старого значения. Вместо этого устаревшие значения хранятся до тех пор, пока все значения в одном блоке хранения не выходят за установленный предел. После этого блок удаляется из основного хранилища целиком. Таким образом, реальное количество хранимых значений может превышать указанный предел в отдельные моменты времени.