TCS Documentation portal logo
Помощь
Обновлена 8 июня 2026 г. в 12:21

Руководство пользователя

Архитектура хранения

Tarantool Column Store – колоночная транзакционно-аналитическая СУБД, построенная на платформе Tarantool Enterprise Edition. TCS наследует от Tarantool базовые возможности хранения и масштабирования:

  • данные хранятся в оперативной памяти;
  • хранение персистентно;
  • доступны механизмы репликации и шардирования.

TCS относится к гибридному классу систем хранения HTAP (Hybrid transactional/analytical processing). Хранилище данных реализовано средствами in-memory СУБД Tarantool. Для работы с данными в колоночном формате используется движок обработки данных MemCS. Такая архитектура позволяет добиться оптимальной производительности аналитических запросов (OLAP) наряду с характерной для Tarantool высокой производительностью при транзакционной нагрузке (OLTP).

Ниже объясняются детали реализации основных механизмов TCS:

Колоночное хранение

Основное хранилище данных TCS работает с данными в колоночном формате.

Ключевое отличие колоночных СУБД от реляционных СУБД с табличным хранением -- использование колонки в качестве единицы хранения вместо таблицы. В реляционной СУБД все поля одного объекта хранятся рядом в виде одной строки таблицы. В свою очередь, в колоночной рядом располагаются все значения одного поля таблицы, а поля одного объекта разнесены по соответствующим колонкам и не хранятся вместе.

Колоночное и табличное хранение

Использование колоночного формата позволяет оптимизировать работу TCS под нагрузкой, характерной для аналитических задач (OLAP), то есть при большом количестве запросов на чтение и вычисление агрегатов.

Чтение данных

Как гибридное решение, TCS предполагает работу под транзакционной нагрузкой на запись. Для консистентности чтения данных в таких условиях TCS использует представления для чтения (read view) – снимки хранилища данных в конкретный момент времени.

В каждый момент времени в TCS существует одно актуальное представление на чтение. Оно обновляется раз в rv_update_ms миллисекунд. Когда приходит запрос на чтение данных, для него используется актуальное представление.

Чтение выполняется в многопоточном режиме. Каждый поток, выполняющий запрос на чтение, использует свое представление. В системе хранится набор всех используемых в данный момент представлений, то есть тех, из которых еще выполняется чтение в рамках выполнения запросов. Когда обработка запроса завершена, и при этом уже создано более актуальное представление, то представление, которые использовалось для этого запроса, помещается в очередь на удаление. Представления из этой очереди удаляются при следующей итерации цикла сборщика мусора (раз в rv_update_ms миллисекунд).

Подробнее о представлениях на чтение см. документацию Tarantool EE.

Доступ к данным

Доступ к данным осуществляется по протоколам SQL Arrow Flight и HTTP. Запросы по всем протоколам принимаются в формате SQL.

В зависимости от режима работы кластера, запросы можно отсылать:

  • напрямую на узлы-хранилища (Storage) – они обрабатывают все виды запросов к данным;
  • через узлы-маршрутизаторы (Scheduler) – они автоматически перенаправляют запросы на узлы Storage.

Режимы работы кластера

Кластер TCS может работать в одном из двух режимов: проксирования или шардирования.

В режиме проксирования:

  • В каждом экземпляре БД в кластере хранятся одинаковые данные.
  • Запросы от клиентов могут автоматически перенаправляться на узлы Storage с помощью узлов Scheduler.
  • При необходимости возможно отсылать запросы напрямую на конкретный узел Storage.

В режиме шардирования:

  • В разных экземплярах БД хранятся разные части общего массива данных.
  • С помощью узлов Scheduler, запросы от клиентов автоматически перенаправляются на узлы Storage с учетом разбиения данных на шарды.
  • Отсылать запросы напрямую на конкретный узел Storage запрещено.

Модель данных

Модель данных в TCS создается и изменяется с помощью инструкций SQL DDL.

Логическая организация данных

TCS использует табличную модель данных, характерную для большинства СУБД, использующих SQL:

  • Данные хранятся в таблицах;
  • Один хранимый объект формирует одну строку таблицы;
  • Структура таблицы определяется набором ее столбцов – колонок;
  • Каждая колонка содержит данные одного типа.

Список поддерживаемых типов данных приведен в разделе Типы данных.

Для логической организации таблиц в TCS используется понятие схемы (schema) -- именованного пространства хранения таблиц. Каждая таблица может содержаться только в одной схеме. Имена таблиц в разных схемах могут повторяться. Схемы агрегируются в каталоги – аналоги баз данных.

Таким образом, полная иерархия хранения данных в TCS выглядит так:

каталог.схема.таблица

По умолчанию используется каталог tcs и схема public.

Типы данных

В TCS используются примитивные типы данных Apache Arrow. Поддерживаются следующие типы:

Тип
Описание
i8
8-битное знаковое целое
i16
16-битное знаковое целое
i32
32-битное знаковое целое
i64
64-битное знаковое целое
u8
8-битное беззнаковое целое
u16
16-битное беззнаковое целое
u32
32-битное беззнаковое целое
u64
64-битное беззнаковое целое
f32
32-битное с плавающей точкой
f64
64-битное с плавающей точкой
decimal
десятичное число с шириной 128 или 256 бит
decimal128
десятичное число с шириной 128 бит
decimal256
десятичное число с шириной 256 бит
utf8
строка UTF-8
bool
логический: true или false
ts
UNIX timestamp в наносекундах

Десятичные числа

Десятичные числа в TCS задаются в формате Apache Arrow и имеют следующие характеристики:

  • ширина в битах (bit width): 128 или 256 бит
  • масштаб (scale)
  • точность (precision)

Ширина (bit width)

Ширина (bit width) может быть задана явно (decimal128 или decimal256), либо вычисляться автоматически на основании точности (precision).

Для чисел с явно заданной шириной (bit width) используются соответствующие значения точности (precision):

  • для decimal128 точность = 38
  • для decimal256 точность = 76

Точность (precision)

Точность (precision) также может быть задана явно или неявно:

  • Если она задана явно (например, decimal(3, 2), здесь точность = 3), то:

    1. Выполняется следующая проверка для точности:

      1 <= precision <= 76

    2. Точность сводится к:

      • 38 (если указанное значение точности <= 38)
      • 76 (если указанное значение точности > 38)
  • Если она задана неявно (например, decimal128(2)), то точность уже известна, исходя из ширины (например, для decimal128 используется точность = 38).

Масштаб (scale)

Масштаб (scale) может быть задан только явно. Например, decimal(3, 2) (здесь масштаб = 2).

Для масштаба всегда выполняется следующая проверка:

0 <= scale <= precision

Примеры десятичных чисел

Пример SQL-инструкции с десятичными числами:

CREATE TABLE t (    d1 decimal128  (9),    d2 decimal256  (1),    d3 decimal (4,  3),    d4 decimal (39, 2),)

где:

  • decimal128(9)

    • bit width = 128
    • scale = 9
    • precision = 38
  • decimal256(1)

    • bit width = 256
    • scale = 1
    • precision = 76
  • decimal(4, 3)

    • bit width = 128
    • scale = 3
    • precision = 38 (поскольку 4 <= 38)
  • decimal(39, 2)

    • bit width = 256
    • scale = 2
    • precision = 76 (поскольку 39 > 38)

Массивы

TCS не поддерживает хранение массивов (данных типа array), но разрешает передачу массива в запросе. См. например функцию array_concat.

Чтение данных

Для обращения к данным в хранилище Tarantool Column Store используются SQL-запросы.

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

Поддерживаемые операторы и функции SQL описаны в [ссылка](../reference#sql-reference[text=Справочнике по SQL]}.

).

Пример запроса на чтение всех объектов таблицы:

SELECT * FROM users
  • HTTP:

    Отправьте POST-запрос на HTTP-адрес /sql.

    Пример запроса на чтение всех объектов таблицы:

    curl -u tcs:tcs -d 'SELECT * FROM users' http://localhost:7777/sql

    Пример запроса на чтение с фильтром:

    curl -u tcs:tcs -d 'SELECT * FROM users WHERE id=1' http://localhost:7777/sql

    Пример чтения из схемы по умолчанию tcs.schema:

    curl -u tcs:tcs -d 'SELECT * FROM users WHERE id=1' http://localhost:7777/sql

Аналитические расчеты

TCS позволяет выполнять аналитические расчеты над хранимыми данными.

Аналитический расчет – это процедура, которая содержит агрегирующие запросы к таблицам и колонкам и возвращает результат выполнения запросов. В аналитических расчетах можно использовать поддерживаемые операторы и функции SQL, описанные в [ссылка](../reference#sql-reference[text=Справочнике по SQL]}.

TCS поддерживает два вида аналитических расчетов:

  • перманентные (хранятся в базе данных)
  • временные (работают только в пределах сессии)

).

Запрос должен содержать SQL-оператор PREPARE, создающий подготовленное SQL-выражение (prepared statement)

Пример: расчет количества записей в таблице.

PREPARE plan(INT) AS SELECT count(*) FROM users WHERE age > $1
  • HTTP:

    Отправьте POST-запрос на HTTP-адрес /sql. В качестве значения используйте SQL-оператор PREPARE, создающий подготовленное SQL-выражение (prepared statement).

    Пример: расчет количества записей в таблице.

    curl -u tcs:tcs -d 'PREPARE plan(INT) AS SELECT count(*) FROM users WHERE age > $1' http://localhost:7777/sql

В качестве параметров для подготовленных SQL-выражений используйте типы данных PostgreSQL.

Выполнение аналитических расчетов

Чтобы выполнить существующий в TCS расчет, воспользуйтесь одним из двух интерфейсов: SQL или HTTP.

  • SQL:

    Отправьте SQL-запрос с EXECUTE через SQL-драйвер.

    Пример:

    EXECUTE plan(0)
  • HTTP:

    Отправьте POST-запрос на HTTP-адрес /sql. JSON-тело запроса должно содержать инструкцию EXECUTE, имя и входные параметры расчета.

    Пример:

    curl -u tcs:tcs -d 'EXECUTE plan(0)' http://localhost:7777/sql

    В ответе TCS отправляет результаты выполнения в следующих секциях:

    • success – результаты успешно выполненных запросов;
    • fail – информация о запросах, которые не удалось выполнить;
    • timings – время, потраченное на разные этапы обработки запроса;
    • plans – вывод EXPLAIN ANALYZE для планов, указанных в запросе.

(queries-computation-manage)

Управление аналитическими расчетами

Чтобы получить список аналитических расчетов и их статусов, отправьте запрос SELECT, содержащий функцию tcs_prepareds.

Пример запроса:

SELECT * FROM tcs_prepareds()

В ответе придёт список, содержащий имена и тела запросов, их зависимости и статусы.

Пример ответа:

name              query                                 depends_on  status0 my_prepared     PREPARE my_prepared A   S SELECT 1    None        Ready

Статус Ready указывает на то, что аналитический расчет готов. Если аналитический расчет не готов (планируется к выполнению), его статус будет Planning.

Чтобы просмотреть текст конкретного аналитического расчета, отправьте запрос SELECT, содержащий функцию tcs_prepareds и имя расчета.

Пример: просмотр текста существующего аналитического расчета my_prepared.

SELECT * FROM tcs_prepareds() WHERE name = my_prepared

Представления для чтения (read views)

TCS предполагает работу под постоянной транзакционной нагрузкой на запись. Для консистентности чтения данных в таких условиях TCS использует представления для чтения (read view) – снимки хранилища данных в конкретный момент времени.

В каждый момент времени в системе существует одно актуальное представление на чтение. Оно обновляется раз в rv_update_ms миллисекунд.

Также есть очередь из используемых в данный момент представлений, из которых еще выполняется чтение в проходящих обработку запросах SQL и прочих.

Когда запрос на чтение обработан, и при этом уже есть более актуальное представление, то представление, которые использовалось для этого запроса, помещается в очередь. При следующей итерации цикла сборщика мусора (раз в rv_update_ms миллисекунд) все представления из очереди удаляются.

Подробнее о представлениях на чтение читайте в документации Tarantool EE.

Нематериализованные SQL-представления (non-materialized views in SQL)

Нематериализованные SQL-представления удобны тем, что позволяют обращаться к большим запросам, как к таблице. Поскольку создаваемое представление не имеет физической формы, указанный запрос будет выполняться каждый раз при обращении к этому представлению.

Создание нематериализованных SQL-представлений

Чтобы создать нематериализованное SQL-представление, отправьте SQL-запрос, содержащий SQL-оператор CREATE VIEW.

Пример: SQL-представление, содержащее список имен всех совершеннолетних лиц в таблице.

CREATE VIEW adults AS SELECT name FROM users WHERE age >= 18;

Использование нематериализованных SQL-представлений

После создания нематериализованное SQL-представление становится доступно:

  • для запросов на чтение,
  • для аналитических расчетов,
  • для использования в других нематериализованных SQL-представлениях; это означает, что в TCS можно создавать вложенные (иерархические) нематериализованные SQL-представления.

Пример: обращение к SQL-представлению adults из SELECT-запроса.

SELECT salary FROM users WHERE name IS IN (SELECT name FROM adults)

Управление нематериализованными SQL-представлениями

Чтобы просмотреть все доступные нематериализованные SQL-представления, отправьте запрос SELECT, содержащий функцию tcs_views:

SELECT * FROM tcs_views()

Чтобы просмотреть текст конкретного SQL-представления, отправьте запрос SELECT, содержащий функцию tcs_views и имя представления.

Пример: просмотр текста существующего SQL-представления adults.

SELECT * FROM tcs_views() WHERE name = adults

Чтобы заместить существующее SQL-представление, отправьте SQL-запрос, содержащий SQL-оператор CREATE OR REPLACE VIEW.

Пример: замещение существующего SQL-представления adults.

CREATE OR REPLACE VIEW adults AS SELECT name FROM users WHERE age >= 16

Чтобы удалить SQL-представление, отправьте SQL-запрос, содержащий SQL-оператор DROP VIEW и имя представления.

Пример: удаление существующего SQL-представления adults.

DROP VIEW adults

Оптимизация запросов на чтение шардированных данных

В TCS предусмотрены правила оптимизации для запросов на чтение шардированных данных:

  • RemotePushDown
  • LocalizedPrepared

Правило RemotePushDown

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

Далее рассмотрим на примерах, как это правило оптимизации влияет на обработку шардированных запросов на чтение. Предположим, что у нас есть шардированная таблица t(a, b) и 3 шарда.

Простое полное сканирование (full scan)

Рассмотрим простой запрос:

SELECT * FROM t

Запросив EXPLAIN на экземпляре Scheduler, можно увидеть физический план следующего вида:

RemoteExec: table=datafusion.public.t, partitioning=Hash([a@0], 3), filter=None  UnionExec    TarantoolExec: table=datafusion.public.t fields=[a, b], ...    BufExec: table=datafusion.public.t fields=[a, b], ...

В этом плане есть узел RemoteExec, который отправляет нижележащий план на шарды для последующего исполнения. Тот план, который он отправляет, назовем удаленным планом. В нашем примере удаленный план – это план с корневым узлом UnionExec.

В описании RemoteExec мы видим следующее:

  • есть соответствие между этим узлом и таблицей t (table=);
  • партицирование данных производится по хэшу колонки a (согласно схеме шардирования);
  • используется пустой фильтр.

В нашем примере таблица будет просканирована на 3 шардах, а все записи отправлены на экземпляр Scheduler и там объединены.

Одношардовый перебор

Рассмотрим более сложный запрос, где для выполнения не обязательно читать данные со всех шардов:

SELECT * FROM t WHERE a = 1

Здесь мы получаем физический план следующего вида:

RemoteExec: table=datafusion.public.t, partitioning=Hash([a@0], 1), filter=datafusion.public.t.a=1  CoalesceBatchesExec: target_batch_size=8192    FilterExec: a@0 = 1      UnionExec        TarantoolExec: table=datafusion.public.t fields=[a, b], ...        BufExec: table=datafusion.public.t fields=[a, b], ...

В описании RemoteExec мы видим следующее:

  • весь план проталкивается внутрь (push down) через RemoteExec;
  • фильтрация выполняется полностью в рамках одного шарда, а по сети пересылаются уже отфильтрованные данные.

Здесь правило RemotePushDown пытается поднять RemoteExec как можно выше.

Для того чтобы посмотреть, как отработало то или иное правило оптимизации, можно использовать запрос EXPLAIN VERBOSE. Он возвращает состояния плана после каждой изменившей его оптимизации. Например, в нашем случае можно видеть, что первоначальный физический план имеет такой вид:

FilterExec: a@0 = 1  RemoteExec: table=datafusion.public.t, partitioning=Hash([a@0], 1), filter=datafusion.public.t.a=1    UnionExec      TarantoolExec: table=datafusion.public.t fields=[a, b], ...      BufExec: table=datafusion.public.t fields=[a, b], ...

Здесь фильтрация осуществляется после сбора данных с шардов, а после прохода правила оптимизации RemotePushDown фильтр проталкивается вниз через RemoteExec, вследствие чего запрос становится лучше локализован в рамках шарда.

Исполнение частичной агрегации на шардах

Правило RemotePushDown также может обеспечить выполнение частичной агрегации на шардах. Рассмотрим запрос:

SELECT count(*) FROM t

Он имеет следующий физический план:

AggregateExec: mode=Final, gby=[], aggr=[count(*)]  CoalescePartitionsExec    RemoteExec: partitioning=UnknownPartitioning(3), filter=None      AggregateExec: mode=Partial, gby=[], aggr=[count(*)]        UnionExec          TarantoolExec: table=datafusion.public.t fields=[], ...          BufExec: table=datafusion.public.t fields=[], ...

Как мы видим, частичная агрегация была перенесена на шард. Заметим, что в этом примере для RemoteExec уже не выводится table, а также используется UnknownPartitioning вместо Hash. Это происходит из-за того, что после исполнения агрегации изменяется выходная схема: поле a в ней больше не присутствует, но появляется поле count(*).

То, какие узлы можно проталкивать внутрь для исполнения на одном шарде, определяется следующими факторами:

  1. Если в запросе указан фильтр, который читает лишь одно значение ключа шардирования (например, a = $1), то запрос может быть полностью локализован и план будет полностью протолкнут под RemoteExec.

  2. В ином случае проталкивание производится до тех пор, пока шард может исполнить соответствующий узел самостоятельно (то есть пока для сбора данных шарду не нужны данные с других шардов). Например, CoalescePartitionsExec не может быть исполнен локально, поскольку для него необходимо собрать данные со всех шардов, тогда как FilterExec может быть исполнен локально.

Правило LocalizedPrepared

Правило оптимизации LocalizedPrepared позволяет полностью предотвратить передачу физического плана с экземпляра Scheduler на экземпляр Storage при исполнении обоих следующих условий:

  1. Исполняется аналитический запрос (prepared statement).
  2. План был полностью локализован.

В таком случае при исполнении аналитического запроса будет использоваться план следующего вида:

PreparedStatementExec: name=query, mode=local {from_cache: true}  RemoteExec: table=datafusion.public.sharded_by_indexed_string, partitioning=Hash([a@0], 1), filter=None    PreparedStatementExec: name=query, mode=remote, metrics=[]\n

Данный план следует читать так: "Исполняется аналитический запрос, локальный для экземпляра Scheduler. Его план состоит из однопартицированного RemoteExec, который отправляет удаленный план на экземпляр Storage для исполнения аналитического запроса."

В этом случае вместо тяжелого плана будет отослан всего один узел (PreparedStatementExec). Далее экземпляр Storage сам запланирует аналитический запрос с этим названием (либо возьмет план для исполнения из кэша) и исполнит его.

Модификация данных

Для выполнения операций модификации данных в Tarantool Column Store используются запросы SQL DML. Их можно отсылать как через SQL-драйвер, так и в виде POST-запроса на HTTP-адрес /sql.

Вставка данных

TCS поддерживает несколько вариантов вставки данных в таблицу:

  • SQL-запрос с помощью SQL-драйверов;
  • SQL-запрос на HTTP-адрес /sql;
  • HTTP-запрос с данными в формате JSON на HTTP-адрес /insert.

Вставка данных через SQL-драйверы

Для вставки данных в таблицу используются SQL-запросы с оператором INSERT вида INSERT INTO table_name { VALUES ( expression [, ...] ) [, ...] | query }.

В одном запросе можно передавать как один, так и несколько объектов для вставки. TCS обрабатывает объекты в том порядке, в каком они указаны в запросе.

В значениях полей можно указывать как конкретные значения, так и null.

Пример:

INSERT INTO target_table VALUES (1, 'One'), (2, 'Two');

Также в запросах можно использовать аргументы-заполнители (placeholders).

Вставка данных через /sql

Вставка данных чере HTTP-адрес /sql производится с помощью SQL-запросов, полностью аналогичных тем, что используются при вставке данных через SQL-драйверы. Алгоритм обработки запросов и их быстродействие здесь также аналогичны.

Вставка данных через /insert

HTTP-адрес /insert используется для выполнения запросов на вставку как более быстрая альтернатива SQL-драйверам и HTTP-адресу /sql.

Вставка через HTTP-адрес /insert работает быстрее, поскольку не требует ресурсоемкого построения планов. При этом способе вставки производятся лишь 2 дополнительных действия:

  • проверка соответствия типов переданных значений и типов колонок;
  • перевод данных в необходимый формат для вставки в Tarantool.

Через HTTP-адрес /insert данные передаются не с помощью SQL-запросов, а с помощью HTTP-запросов в сериализованном виде в формате JSON.

Требования к HTTP-запросам:

  • Запросы отсылаются на HTTP-адрес вида /insert/$name, где /$name – это имя таблицы.
  • Тело запроса должно содержать массив описаний вставляемых объектов.
  • Для каждой строки указываются значения вида "имя_колонки": значение. Их требуется указывать для всех колонок, которые есть в таблице.
  • Порядок колонок в запросе может быть любым. Например, [{ "a": 1, "b": 2 }] эквивалентно [{ "b": 2, "a": 1 }].
  • Значения null можно опускать. Например, [{ "a": 1, "b": null }] эквивалентно [{ "a": 1 }].
  • В заголовке запроса нужно обязательно указывать content-type: application/json.

Пример: вставка данных в таблицу target_table с помощью утилиты curl.

curl -u 'tcs:tcs' -H 'Content-Type: application/json' -d '[{"a":1, "b":-1}, {"a":2, "b": -2}]' http://localhost:7777/insert/target_table

Вставка данных из выборки (insert into select)

Для вставки в таблицу объектов из выборки используйте SQL-запрос вида INSERT INTO table_1 SELECT attribute FROM table_2.

Пример:

INSERT INTO names SELECT name FROM users

В операциях вставки из выборки можно использовать все имеющиеся в TCS возможности SELECT-запросов, например осуществлять выборку из нескольких таблиц (оператор JOIN) и задавать условия с помощью оператора WHERE. Подробнее см. Справочник по SQL > Инструкция SELECT.

Порядок полей таблиц и типы должны совпадать. Например, возьмем две таблицы:

  • таблицу names, которая содержит 2 поля, name и age (именно в таком порядке они объявлены в модели данных);
  • таблицу users, которая содержит поля address, age, name и прочие.

Следующий запрос составлен с учетом порядка полей в этих таблицах:

INSERT INTO names SELECT name, age FROM users

Обновление данных

Для обновление данных в таблице используйте запрос с SQL-оператором UPDATE.

Поддерживается следующий синтаксис запросов:

UPDATE table_nameSET column1 = value1, column2 = value2, ...WHERE condition;

Пример:

UPDATE namesSET name = 'Anna Danilova', age = '32'WHERE id = 10

Удаление данных

Для удаления объектов из таблиц используйте запрос с SQL-оператором DELETE.

Пример:

DELETE FROM a WHERE i > 1 LIMIT 100

Управление запросами

Просмотр списка активных запросов

Эта возможность не поддерживается в текущей версии TCS.

Отмена запроса

Эта возможность не поддерживается в текущей версии TCS.

Отправка нескольких SQL-инструкций (multi-statement)

На HTTP-адрес /sql можно отправлять сразу несколько SQL-инструкций, разделенных точкой с запятой (;). Это могут быть любые SQL-инструкции, поддерживаемые TCS.

TCS обрабатывает инструкции в указанном порядке и возвращает список статусов.

Если обработка какой-либо инструкции заканчивается ошибкой, то TCS прекращает обработку инструкций и возвращает список статусов.

Пример запроса:

POST http://localhost:7777/sql HTTP/1.1Content-Type: application/jsonSELECT name FROM users; INSERT INTO names SELECT name FROM users; SELECT * FROM names ORDER BY name

Если, например, вторая инструкция (INSERT INTO names SELECT name FROM users) завершится ошибкой, то третья инструкция тоже не выполнится.

Управление транзакциями

В текущей версии TCS ни в одном из интерфейсов (HTTP, JDBC\ADBC) не поддерживается интерактивное управление транзакциями (COMMIT, ROLLBACK).

Однако, если SQL-операция по изменению данных (DELETE, INSERT, UPDATE) затрагивает большой массив данных (больше максимального размера пакета), то она разбивается на несколько под-операций, которые далее обрабатываются как единая транзакция. При этом если какая-либо из под-операций завершается некорректно, то оставшиеся под-операции не выполняются, но (в отличие от классических транзакций) результат предыдущих под-операций не откатывается.

Пример: При удалении 50 тысяч строк создается 7 под-операций удаления (50000 / 8192 примерно равно 6,1). Если пятая под-операция из этих 7 завершится некорректно, то эта и остальные две под-операции не применятся, но результат первых 4 операций останется в базе.

Отправка параметризованных SQL-запросов по HTTP

TCS поддерживает отправку параметризованных SQL-запросов по HTTP. Параметры запроса передаются списком в соответствующей переменной:

  • args – список параметров при однократном вызове запроса (поддерживается для всех видов запросов):

    curl -u tcs:tcs -X POST -H "Content-Type: application/json" -d '{ "query": "SELECT * FROM t WHERE a>$1", "args": [0] }' http://localhost:7777/sql
  • bulk_args – список списков параметров для множественных вызовов (поддерживается для запросов INSERT, UPDATE, DELETE):

    curl -u tcs:tcs -X POST -H "Content-Type: application/json" -d '{ "query": "INSERT INTO t VALUES($1, $2)", "bulk_args": [[1,1], [2,2]] }' http://localhost:7777/sql

Принудительная маршрутизация запросов

В режиме проксирования экземпляры Scheduler могут принудительно отправлять запросы лишь на те экземпляры Storage, которые настроены на работу только в режиме чтения (read-only) -- либо наборот, принудительно исключать такие экземпляры Storage из маршрутизации.

Для отправки запроса на определенный вид экземпляров Storage нужно в заголовке запроса указать параметр x-tcs-route и тот тип экземпляров Storage, на которые нужно маршрутизировать запрос:

  • ro для отправки на экземпляры, настроенные только на чтение;
  • rw для исключения read-only экземпляров из маршрутизации (в этом случае запрос будет отправлен на экземпляр, настроенный на чтение-запись);
  • any для отправки на все типы экземпляров (это аналогично тому, когда заголовок x-tcs-route не указан).

Балансировка нагрузки для таких запросов осуществляется только среди указанного типа экземпляров Storage.

Далее приводятся примеры отправки запросов на RW-экземпляр Storage для разных интерфейсов.

  • Для ADBC/JDBC:

    header_key = f"{DatabaseOptions.RPC_CALL_HEADER_PREFIX.value}x-tcs-route"             db_kwargs[header_key] = rw      self.conn = adbc_driver_flightsql.dbapi.connect(          self.uri,          db_kwargs=db_kwargs,          autocommit=True,      )
  • Для HTTP:

    curl --location-trusted -L -X POST -u tcs:tcs -H "x-tcs-route:rw" -d 'CREATE TABLE t(a int)' http://localhost:7780/sql

Включение схемы данных в ответ

По умолчанию, ответы на запросы к TCS содержат массив данных без указания схемы. Например:

$ curl -u tcs:tcs -d 'insert into t values(1)' http://127.0.0.1:7777/sql{"responses":[{"is_success":true,"rows":[{"count":1}],"timings":{"collect":"494.295µs"}}]}%

При необходимости можно включить в ответ схему данных. Для этого в заголовке запроса нужно указать параметр x-tcs-include-schema: true. Тогда в начале ответа возвращается схема данных в формате колонка:тип. Причем схема данных включается в ответ, даже если возвращается 0 строк. Например:

$ curl -u tcs:tcs  -d 'insert into t values(1)' -H 'x-tcs-include-schema: true' http://127.0.0.1:7777/sql{"responses":[{"is_success":true,"schema":[{"name":"count","type":"UInt64"}],"rows":[{"count":1}],"timings":{"collect":"311.063µs"}}]}

Работа со сложными запросами

TCS не накладывает ограничений на следующее:

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

Разрешено использовать подзапросы, а также расчетные значения подзапросов в последующих подзапросах.

Работа с пользовательскими функциями и процедурами

Текущая версия TCS не поддерживает работу с пользовательскими функциями/процедурами.

Работа с индексами

TCS поддерживает работу с индексами типа key-value.

Особенности индексов key-value в TCS

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

Этот вид индексов работает только для запросов на равенство значений. Запросы на сравнение значений (больше/меньше) пока не поддерживаются.

Создание индекса key-value

См. CREATE INDEX.

Удаление индекса key-value

См. DROP INDEX.

Перестроение индекса key-value

Для всех индексов key-value проводится автоматическая переиндексация по мере изменения данных в таблице. Принудительно перестраивать индексы вручную не требуется.

Первичные индексы

Первичный индекс задается при создании таблицы. Он может быть:

  • задан пользователем, например:

    CREATE TABLE t(    a int,    b int,    c int,    PRIMARY KEY(a))
  • либо создан автоматически, например:

    CREATE TABLE t(    a int,    b int,    c int)

    Здесь в таблицу t будет автоматически добавлено поле rowid (оно станет первым полем в таблице), а по нему будет создан первичный индекс.

У таблицы может быть только один первичный индекс. Все остальные индексы в таблице являются вторичными.

Первичный индекс должен быть уникальным.

Он может строиться как по одному столбцу, так и по нескольким (см. составные индексы).

Вторичные индексы

Вторичные индексы могут быть только неуникальными (задать UNIQUE для них в текущей версии TCS нельзя).

Они могут строиться как по одному столбцу, так и по нескольким (см. составные индексы).

Составные индексы

Составной индекс может содержать более одного столбца.

Для создания составных KV-индексов поддерживаются запросы следующего вида:

  • первичный составной индекс:

    CREATE TABLE t(    a int,    b int,    c int,    PRIMARY KEY(a, c))
  • вторичный составной индекс:

    CREATE INDEX SYNC test_index ON departments(name, manager, size);

Чтение с использованием индекса осуществляется при наличии условия (в т.ч. сортировки) по первому или по нескольким полям индекса. Например:

SELECT * FROM departments WHERE name = 'HR' AND manager != 'Ivanov' ORDER BY size;

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

Порядок сортировки по индексу

По умолчанию, все индексы в TCS создаются с возрастающим порядком сортировки. Например, инструкция CREATE INDEX t(a,b,c) имеет тот же эффект, что и CREATE INDEX t(a ASC, b ASC, c ASC).

При необходимости порядок сортировки для индекса, заданного пользователем (как первичного, так и вторичного), можно задать с помощью ключевых слов desc (убывающий порядок) и asc (возрастающий порядок). Для составных индексов порядок сортировки можно задавать индивидуально для каждой компоненты. Например:

-- первичный составной индексCREATE TABLE t(a int, b int, primary key(b DESC, a ASC))-- вторичный составной индексCREATE INDEX my_ind ON t(b DESC, a ASC)

Для первичного индекса, создаваемого автоматически (rowid), также можно явным образом задать порядок сортировки. Например:

CREATE TABLE t(a int, primary key(rowid DESC))

Здесь выборка по первичному ключу вернет данные в порядке, обратном порядку их вставки.

Порядок чтения по индексу

Данные возвращаются в том порядке, который задан для индекса, по которому производится выборка. В частности, выборка по вторичному индексу может вернуть данные в ином порядке, чем выборка по первичному индексу. Например, если нужно читать данные в порядке, обратном вставке, но для таблицы не задан убывающий первичный ключ, то можно задать вторичный индекс с нужным порядком:

CREATE INDEX i ON t(a, rowid DESC)

В результате при чтении по индексу i данные будут предоставляться в порядке убывания rowid.

Также можно явно задавать порядок чтения по вторичному индексу, в состав которого входит автоматически создаваемый первичный индекс (rowid). Например:

CREATE INDEX sec ON t(a, rowid desc)

Здесь записи в выборке по составному индексу a, rowid будут отсортированы вначале по a (в убывающем порядке), а затем внутри одинаковых групп – по rowid (в том порядке, который был указан при создании первичного индекса по rowid).

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

Для планировщика можно явно указать конкретный индекс (с заданным в этом индексе порядком чтения) с помощью функции plan_with с аргументом use_index.

Оптимизации при работе с индексами

Индексы (и первичные, и вторичные) оптимизируют запросы с указанием равенства и диапазона значений.

Для эффективной работы фильтрующее выражение в запросе должно сначала задавать условия равенства по первым компонентам индекса (если он составной), а затем – условия вхождения в диапазон для последующей компоненты: col1=x1, col2=x2, ..., coln in [ln, rn]

Например, если индекс состоит из одной компоненты (a), то с его использованием можно сделать запросы со следующими фильтрами:

a = 1a > 1a > 2 AND a < 3a < 3

Если индекс содержит две компоненты (a, b), то в запросе можно задать следующие фильтры:

a = 1 AND b > 2a = 1 AND b = 1a = 1 AND b > 3a > 1a > 1 AND a < 10

Индексы используются планировщиком:

  • при сканировании, например:

    EXPLAIN SELECT * FROM t WHERE a = 1 AND c = 2----logical_plan TableScan: t projection=[a, b, c], full_filters=[t.a = Int32(1), t.c = Int32(2)]physical_plan01)IndexScanExec: table=tcs.public.t, index=pk_tcs_public_t, direct_projection=[a, b, c]02)--Range: (a = 1) AND (c = 2)
  • при поиске по диапазону, например:

    EXPLAIN SELECT * FROM t WHERE a > $1 AND a < $10----logical_plan TableScan: t projection=[a, b, c], full_filters=[t.a > $1, t.a < $10]physical_plan01)IndexScanExec: table=tcs.public.t, index=pk_tcs_public_t, direct_projection=[a, b, c]02)--Range: $1 < a < $10

IndexScanExec, единый узел плана выполнения для пользовательских таблиц в TCS, сначала предпринимает попытку исполнить проекцию всех требуемых столбцов с помощью первичного индекса, без сканирования всей таблицы. Если это не удается, то предпринимаются дополнительные попытки поиска.

Таким образом, при сканировании исполняются проекции двух видов:

  • прямая проекция – проводится только с использованием первичного индекса.
  • косвенная проекция – проводится дополнительно для каждой записи с использованием вторичного индекса.

Косвенная проекция в среднем работает медленнее, поэтому планировщик пытается по возможности использовать первичные индексы.

В примерах выше ответ не содержит информацию о косвенных проекциях, поскольку там исполняются только прямые проекции (по первичному индексу). Рассмотрим пример запроса, где исполняются оба вида проекций:

CREATE TABLE t(a int, b int, c int)-- создаем вторичный индексCREATE INDEX SYNC ta ON t(a)EXPLAIN SELECT * FROM t WHERE a = 1----logical_plan TableScan: t projection=[a, b, c], full_filters=[t.a = Int32(1)]physical_plan01)IndexScanExec: table=tcs.public.t, index=ta, direct_projection=[a, rowid], indirect_projection=[b, c]02)--Range: a = 1

Здесь планировщик производит выборку по индексу ta. Сначала он смог исполнить проекцию колонки a и rowid с помощью первичного индекса (прямая проекция). А для колонок b и c пришлось построчно исполнить косвенные проекции.

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

Вытеснение данных

Вытеснение данных подразумевает удаление данных из БД, либо перемещение данных из оперативной памяти на диск с целью охлаждения данных.

Вытеснение данных из TCS выполняется автоматически по мере заполнения хранилища, либо по истечении времени хранения данных.

Вытеснение данных по количеству записей

При добавлении новых записей сверх лимита одновременно хранимых записей наиболее старые записи удаляются.

Вытеснение данных по количеству записей организовано потаблично: для каждой таблицы может быть определен свой лимит количества одновременно хранимых записей.

Лимит задается с помощью параметра MAX_ROWS и указания максимального количества записей в таблице:

  • при создании таблицы, например: CREATE TABLE t MAX_ROWS 10000
  • при изменении таблицы, например: ALTER TABLE t MAX_ROWS 100000

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

По умолчанию, лимит для таблиц не установлен: без явного указания лимита MAX_ROWS при создании таблицы вытеснение данных из нее не производится.

При необходимости можно в дальнейшем отключить вытеснение, задав значение лимита равное 0, например: ALTER TABLE t MAX_ROWS 0.

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

Вытеснение данных по времени

При обнаружении данных, которые хранятся сверх указанного срока, все устаревшие данные удаляются или перемещаются на внешний том. Вытеснение (удаление или перемещение) происходит по расписанию, в фоновом режиме.

Вытеснение данных по времени организовано потаблично: для каждой таблицы могут быть определены свои условия.

Настройка вытеснения для новых таблиц

Чтобы настроить вытеснение по времени для новой таблицы, нужно сделать вызов CREATE TABLE следующего вида:

CREATE TABLE table_name (    id u64,    created_at ts)[TTL expr    DELETE | INTO VOLUME 'volume_name'    SCHEDULE 'cron_expr']

где:

  • (Обязательно) Столбец типа ts (например, created_at ts). По этому столбцу TCS создает вторичный индекс для быстрого поиска данных, подлежащих вытеснению.

  • (Обязательно) TTL expr – выражение, определяющее момент устаревания данных (например, created_at + INTERVAL 7 DAYS). Выражение expr должно возвращать значение типа ts и имеет следующий формат:

    <timestamp_column> + INTERVAL <time_interval> <interval_type>

    где:

    • (Обязательно) <timestamp_column> – указанный выше столбец типа ts с временными метками;
    • (Oбязательно) INTERVAL – длительность хранения относительно временной метки, состоящая из целочисленного значения <time_interval> и типа интервала <interval_type> (например, DAYS, MONTHS, YEARS, HOURS).
  • (Обязательно) Действие по истечении TTL:

    • DELETE – удаление данных
    • INTO VOLUME 'volume' – перемещение данных на указанный внешний том
  • (Обязательно) SCHEDULE – частота проверки и вытеснения данных. Задается с использованием синтаксиса планировщика crontab, например:

    • '@hourly' (каждый час)
    • '30 * * * *' (раз в 30 минут)

    Настройка ежедневной проверки с помощью сокращений '@daily' и @midnight не поддерживается. Вместо этого можно использовать выражение (0 0 * * *) (ежедневная проверка в полночь).

Пример 1: создание таблицы с вытеснением (удалением) данных старше 7 дней, с ежедневной проверкой.

CREATE TABLE my_table (    id u64,    created_at ts)TTL created_at + INTERVAL 7 DAYS    DELETE    SCHEDULE '(0 0 * * *)'

Пример 2: создание таблицы с вытеснением (охлаждением) данных старше 7 дней на внешний том, с ежедневной проверкой.

CREATE TABLE my_table (    id u64,    created_at ts)TTL created_at + INTERVAL 7 DAYS    INTO VOLUME 'my_volume'    SCHEDULE '(0 0 * * *)'

Настройка вытеснения для существующих таблиц

В текущей версии TCS данная возможность не поддерживается.

Охлаждение данных

"Охлаждение данных" подразумевает перенос данных из горячего хранилища (колоночного хранилища TCS в оперативной памяти), которое обеспечивает максимально быстрый доступ к данным, в холодное (хранилище, использующее дисковое пространство для хранения данных), когда данные устаревают. Это позволяет увеличить объем хранимых данных при ограниченном объеме оперативной памяти.

Особенности охлаждения данных в TCS

Возможности и ограничения текущей версии TCS:

  • Охлаждение данных настраивается потаблично, с использованием механизма TTL (Time to Live), который обеспечивает автоматическое удаление или перемещение данных по истечении заданного времени. Охлаждение по количеству записей (объему) и по прочим условиям (например, по триггеру) не поддерживается.
  • Настройка охлаждения доступна только для новых таблиц. Для уже существующих таблиц эта возможность не поддерживается.
  • Поддержана работа с данными в формате Parquet и Iceberg.
  • Не поддержаны некоторые типы данных: логический (bool), знаковые целочисленные до i32 (i16, i8) и все беззнаковые целочисленные (u64, u32, u16, u8).
  • Охлаждение осуществляется только на локальный диск. Работа с хранилищами S3 не поддерживается. Также пока недоступно изменение существующего локального тома.
  • Не поддержано партиционирование данных во внешнем хранилище (параметр PARTITION BY в запросах CREATE TABLE и ALTER TABLE).
  • Охлаждение – однонаправленный процесс. После сброса на диск данные не возвращаются обратно в память.
  • Данные на диске нельзя менять, в том числе и схему данных.
  • Вставка данных всегда производится сначала в оперативную память, где данные накапливаются и охлаждаются в соответствии с выбранной стратегией.
  • Метрики мониторинга для охлаждения данных пока недоступны.
  • Охлаждение данных работает только в режиме проксирования. В режиме шардирования охлаждение не поддерживается.

Управление томами

Создание томов для хранения данных

Перед настройкой процесса охлаждения данных необходимо создать внешний том (external volume) -- специальное описание внешнего хранилища, куда будут вытесняться данные.

Для организации локального хранения используется команда следующего вида:

CREATE EXTERNAL VOLUME my_local_volume AS  '/tmp/AAA'WITH (  'format' = 'iceberg',  'db_file_name' = 'my-iceberg.catalog');

где:

  • (Обязательно) Путь к локальному хранилищу указывается без префикса file://.

  • (Обязательно) Блок WITH содержит следующие параметры:

    • (Обязательно) format – формат хранения данных. Поддерживается только одно значение: iceberg. Тем не менее этот параметр является обязательным.
    • (Необязательно) db_file_name – путь к тому в tcs_volumes_list() и DESCRIBE. В данном примере путь будет равен /tmp/AAA/my-iceberg.catalog. По умолчанию (если бы параметр db_file_name не был задан), путь бы равнялся /tmp/AAA/my_local_volume.

Получение информации о томах

Получение общей информации о томах

Для получения общей информации о подключенных внешних томах используется следующая команда:

SELECT * from tcs_volumes_list()

Возвращаемые данные:

  • имя внешнего тома
  • формат данных
  • идентификатор URI (путь хранения данных)
  • количество таблиц, связанных с этим томом

Пример:

SELECT * from tcs_volumes_list() ORDER BY name----volume1  iceberg  sqlite:///tmp/A/volume1  42volume2  iceberg  sqlite:///tmp/B/volume2  10volume3  iceberg  sqlite:///tmp/C/volume3   0

Получение детальной информации о томе

Для получения расширенной информации о настройках и характеристиках выбранного внешнего тома используется команда следующего вида:

DESCRIBE STORAGE_INTEGRATION my_volume

где:

  • (Обязательно) my_volume – имя внешнего тома.

Помимо общей информации, в ответе возвращается:

  • имя набора реплик, который в случае формата Iceberg используется как пространство имен (namespace) для данных таблиц
  • список связанных таблиц
  • тип каталога

Пример:

DESCRIBE STORAGE_INTEGRATION volume1----volume1  iceberg  sqlite:///tmp/A/volume1 replicaset1  []  local-sqlite

Удаление тома

Для удаления внешнего тома используется команда следующего вида:

DROP EXTERNAL VOLUME [ IF EXISTS ] my_volume;

где:

  • (Необязательно) IF EXISTS – параметр, который предотвращает возникновение ошибки, если удаляемый том не существует.
  • (Обязательно) my_volume – имя удаляемого внешнего тома.

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

При попытке удалить внешний том, который задействован в процессе охлаждения данных, TCS блокирует операцию удаления, формирует сообщение об ошибке и предоставляет полный список таблиц, зависящих от данного тома.

Чтение охлажденных данных

Для чтения определенного вида данных в рамках текущей сессии нужно установить переменную tcs.volume_read_mode:

  • SET tcs.volume_read_mode = 'skip' – не читать данные с диска.
  • SET tcs.volume_read_mode = 'fallback' (по умолчанию) – сначала пытаться читать данные из памяти, если там пусто – читать с диска.
  • SET tcs.volume_read_mode = 'union' – читать данные параллельно и из памяти, и с диска.

Управление таблицами с TTL (Time To Live)

См. Вытеснение данных по времени.

Работа с драйверами JDBC/ADBC

TCS поддерживает работу с общедоступными драйверами для интерфейсов JDBC и ADBC по SQL-протоколу Apache Arrow Flight.

Установка драйверов

Скачайте установочный пакет нужного драйвера по ссылке:

Подключение драйверов

Подключение драйвера JDBC к редактору DBeaver

  1. В DBeaver добавьте драйвер JDBC для Arrow Flight SQL в качестве нового драйвера:

    a. В меню выберите пункт Database > Driver Manager.

    b. В диалоговом окне Driver manager нажмите Create.

    c. В разделе Settings выполните следующие действия:

    • В поле Name укажите имя драйвера, например JDBC Driver for Arrow Flight SQL.
    • В поле Driver Type убедитесь, что выбран тип драйвера Generic.
    • В поле Class Name укажите org.apache.arrow.driver.jdbc.ArrowFlightJdbcDriver.
    • В поле URL Template укажите jdbc:arrow-flight-sql://{host}:{port} (например, jdbc:arrow-flight-sql://localhost:50051).
    • В поле Default Port укажите порт 50051.

    d. В разделе Libraries нажмите Add File и выберите .jar-файл для драйвера JDBC для Arrow Flight SQL.

    e. Нажмите OK.

  2. Создайте подключение к DBeaver, использующее ваш драйвер:

    a. Выберите Database > New Connection from JDBC URL.

    b. В поле Create New Connection в диалоговом окне JDBC URL введите jdbc:arrow-flight-sql://{host}:{port}?useEncryption=0 (например, jdbc:arrow-flight-sql://localhost:50051?useEncryption=0).

    Свойство useEncryption=0 (false) необходимо указывать явно, поскольку при работе с текущей версией TCS поддерживаются только незашифрованные JDBC-соединения. Значение по умолчанию для этого свойства равно 1 (true).

    В результате DBeaver добавит ваш драйвер в список Drivers.

    c. Выберите ваш драйвер в списке Drivers и нажмите Next.

    d. В диалоговом окне Connect to a Database укажите свои учетные данные для аутентификации. При работе с текущей версией TCS поддерживаются только JDBC-соединения по имени пользователя и паролю.

    Учетные данные задаются в конфигурации TCS.

    e. (необязательно) Нажмите Test Connection. Если подключение работает, откроется диалоговое окно Connection Test, в котором указывается, что DBeaver может подключиться к TCS. После попытки подключения соединение закрывается. Нажмите OK.

    f. Нажмите Finish.

Подключение драйвера ADBC к Apache Superset

  1. Склонируйте локально репозиторий Apache Superset https://github.com/apache/superset.

  2. В локальном репозитории Apache Superset создайте файл docker/requirements-local.txt и впишите в него пакеты с зависимостями:

    pyarrow==15.0.0flightsql-dbapi==0.2.2adbc-driver-flightsql==1.4.0psycopg2-binary==2.9.10
  3. Соберите и запустите Docker-образ Apache Superset с помощью Docker Compose:

    export TAG=4.1.1docker compose -f docker-compose-image-tag.yml up

    Подробнее см. https://superset.apache.org/docs/installation/docker-compose/.

  4. Подключитесь к веб-интерфейсу Apache Superset по HTTP-адресу http:/localhost:8088.

  5. Добавьте новое соединение datafusion+flightsql://tcs:tcs@{host}:{port}?insecure=True (например, datafusion+flightsql://tcs:tcs@host.docker.internal:50051?insecure=True).

    Подробнее см. https://superset.apache.org/docs/configuration/databases#connecting-through-the-ui.

Параметры строки соединения

Параметры строки соединения для каждого драйвера описаны в документации Apache Arrow:

Работа с индексами

Работа с индексами через JDBC

Для работы с первичными индексами через JDBC доступна функция getPrimaryKeys(), которая возвращает описания колонок всех первичных индексов для указанной таблицы.

См. подробнее в документации Oracle.

Работа с индексами через ADBC

Драйвер ADBC, использующийся в текущей версии TCS, не поддерживает работу с индексами.

Работа с нематериализованными SQL-представлениями

  • Создание SQL-представления: доступно через SQL-запрос.

  • Просмотр списка всех доступных SQL-представлений:

    • В редакторе DBeaver: нажать кнопку Refresh, все доступные SQL-представления отобразятся в списке Views.
    • В редакторе Superset: нажать кнопку Refresh, все доступные SQL-представления отобразятся в списке TABLE.
  • Просмотр текста SQL-представления: в любом редакторе выбрать SQL-представление в списке, рядом отобразится его текст.

  • Замещение SQL-представления: доступно через SQL-запрос.

  • Удаление SQL-представления: доступно через SQL-запрос.

Работа с аналитическими расчетами через JDBC/ADBC

Подробнее про аналитическиа расчеты (prepared statements) в TCS см. в разделе .

Работа с аналитическими расчетами через JDBC

Требуется JDBC-драйвер flight-sql-dbc-driver версии не ниже 18.3.0.

Для работы с этим драйвером нужно установить зависимость в клиентском приложении.

Пример: добавление зависимости в pom.xml:

<dependency>    <groupId>org.apache.arrow</groupId>    <artifactId>flight-sql-jdbc-driver</artifactId>    <version>18.3.0</version></dependency>

Пример: строка соединения:

jdbc:arrow-flight-sql://localhost:50051?useEncryption=false&user=tcs&password=tcs

Работа с аналитическими расчетами через ADBC

Требуется драйвер go adbc версии не ниже 1.7.0.

Пример кода создания/вызова:

prepared, err := db.Prepare("SELECT * FROM t WHERE a=$1")if err != nil {    log.Fatalf("Failed to prepare the statement: %v", err)}var num int32var str stringif err = prepared.QueryRow(1).Scan(&num, &str); err != nil {    log.Fatalf("Failed to execute query: %v", err)}fmt.Println(num, str)

Пакетная загрузка данных через JDBC

Пакетная загрузка данных через JDBC осуществляется с помощью вставки следующего вида:

INSERT INTO таблица (столбец1, столбец2) VALUES ($1, $2);

Пример кода:

static String singleRowPreparedInsert = "INSERT INTO t VALUES($1, $2, $3, $4)";static void runBatchInsert(Connection conn) throws SQLException {    try (var statement = conn.prepareStatement(singleRowPreparedInsert)) {        for (int i = 2; i <= 5; ++i) {            statement.setInt(1, i);            statement.setInt(2, i);            statement.setString(3, String.format("%d", i));            statement.setBoolean(4, true);            statement.addBatch();        }        statement.executeBatch();    }}

Работа с сессиями

Порядок работы с сессиями в TCS разнится в зависимости от протокола.

http-сессии

Для протокола HTTP каждый запрос выполняется в отдельной сессии. Она автоматически открывается при получении запроса и закрывается по окончании обработки.

flightsql-сессии

Для протокола Arrow Flight SQL сессию необходимо открывать явным образом с помощью запроса Handshake. Сессия должна быть создана до отсылки всех SQL-запросов, которые будут осуществляться в рамках этой сессии, в т.ч. запросов SET, с помощью которых можно задавать параметры сессии.

Закрытие сессии происходит по запросу CloseSession.

Также сессия закрывается автоматически по истечении макcимальной длительности сессии (параметр session_expiration_secs, по умолчанию – 8 часов).

Подробнее см. документацию Arrow Flight RPC и Arrow Flight SQL.

Масштабирование

Репликация

Поддерживаются стандартные функции синхронной/асинхронной репликации Tarantool.

Шардирование

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

Для запросов на чтение в режиме шардирования предусмотрены специальные оптимизации.

Особенности работы шардирования в TCS

Ограничения текущей версии TCS:

  • При переходе на шардированную конфигурацию требуется полная перезаливка данных.

  • Режим шардирования (параметр mode.sharded) не рекомендуется включать, если в конфигурации кластера не заданы хотя бы 2 шарда.

  • Распределение данных между шардами осуществляется на основе актуальной конфигурации кластера. Любые изменения в конфигурации наборов реплик после начальной загрузки данных могут вызвать нарушения в работе механизма шардирования. К критическим изменениям относятся:

    • Переименование существующих наборов реплик;
    • Удаление наборов реплик;
    • Добавление новых наборов реплик.

    В случае проведения подобных операций после изменения конфигурации необходима полная перезаливка данных для обеспечения корректной работы системы шардирования.

Создание шардированных таблиц

Для создания шардированной таблицы используется команда с параметром SHARDED BY, где указывается ключ, по которому будет проводиться шардирование.

Ключ шардирования может быть строкой, числом или составным ключом.

При выборе ключа рекомендуется руководствоваться несколькими принципами:

  • запросы должны быть максимально локализованы;
  • данные должны быть сбалансированы по ключу.

Пример: создание шардированной таблицы с составным ключом

CREATE TABLE t(    a i32,    b utf8,    c u64,    d bool)SHARDED BY a, b

Шардированные таблицы можно создавать, только если кластер работает в режиме шардирования.

Как и все прочие запросы к кластеру в режиме шардирования, запросы на создание таблицы следует отправлять через экземпляр Scheduler, а не напрямую через экземпляр Storage.