Расширенные типы данных

Этот документ описывает расширенные типы данных, поддерживаемые YMatrix.

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

  1. Набор метрик непредсказуем, что означает частые изменения схемы таблицы.
  2. Количество метрик превышает максимальный лимит столбцов YMatrix — 1600.

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

Существует множество способов реализации расширенных типов данных, например, использование пользовательских форматов сериализации, закодированных в столбцы типа text. YMatrix предоставляет два расширенных типа данных:

  1. JSON / JSONB
  2. MXKV

1 JSON / JSONB

Типы JSON и JSONB унаследованы от PostgreSQL. В отличие от прямого хранения строк JSON в текстовых столбцах, типы JSON/JSONB предоставляют встроенные функции для распространённых операций, таких как извлечение пар ключ-значение, объединение и удаление.

JSON и JSONB используются аналогично и могут взаимно преобразовываться. Их различия:

  1. JSON хранится как обычный текст; JSONB — в двоичном формате.
  2. JSON обеспечивает более высокую производительность записи, так как при вставке не требуется преобразование в двоичный формат.
  3. JSONB обеспечивает более быстрый парсинг благодаря внутреннему двоичному представлению.

Ниже приведены распространённые операции с типами JSON / JSONB:

1.1 Извлечение значений с помощью ->

=# SELECT '{"a":1, "b":2, "c":3}'::json->'a';
 ?column?
----------
 1
(1 row)

Для вложенных структур JSON используйте -> несколько раз:

=# SELECT '{"a":1, "b":2, "c":{"d":2}}'::json->'c'->'d';
 ?column?
----------
 2
(1 row)

1.2 Удаление ключей

Используйте оператор - для удаления ключа. При выполнении операций записи над объектами JSON сначала преобразуйте их в JSONB:

=# SELECT '{"a":1, "b":2, "c":3}'::jsonb - 'a';
     ?column?
------------------
 {"b": 2, "c": 3}
(1 row)

1.3 Объединение пар ключ-значение

Используйте оператор || для объединения двух объектов JSONB:

=# SELECT '{"a":1, "b":2}'::jsonb || '{"c":3}'::jsonb;
         ?column?
--------------------------
 {"a": 1, "b": 2, "c": 3}
(1 row)

1.4 Обновление значений

При пересечении ключей оператор || обновляет значение:

=# SELECT '{"a":1, "b":2}'::jsonb || '{"b":3}'::jsonb;
     ?column?
------------------
 {"a": 1, "b": 3}
(1 row)

Для дополнительных операций с JSON обратитесь к документации PostgreSQL: документация.

2 MXKV

Эта тема рассмотрена в обучающем видео: Моделирование данных YMatrix и спatio-temporal модель распределения

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

  1. Количество собираемых метрик превышает лимит в 1600 столбцов YMatrix.
  2. Различные модели устройств сообщают сильно отличающиеся наборы метрик, что приводит к множеству значений NULL.
  3. Набор метрик заранее неизвестен, что вызывает частые изменения схемы.

Традиционные решения включают:

  1. Сериализацию нескольких столбцов в поле переменной длины.
  2. Использование типов данных JSON или JSONB.

Хотя эти подходы упрощают операционную сложность, они страдают от низкой производительности.

MXKV был разработан для устранения этих ограничений. MXKV — это высокопроизводительный и масштабируемый тип хранения, разработанный YMatrix. Он используется аналогично JSON, но обладает преимуществами в эффективности: MXKV использует двоичное хранение и интегрируется с алгоритмами сжатия YMatrix для достижения компактного хранения и высокой производительности запросов.

Примечание!
Эта функция доступна только в корпоративной версии.

2.1 Использование

2.1.1 Создание расширения и проверка

Тип данных MXKV входит в расширение MatrixTS. Сначала создайте расширение:

=# CREATE EXTENSION matrixts;

Убедитесь, что MXKV включён:

=# SELECT '{}'::mxkv_text;
 mxkv_text
-----------
 {}
(1 row)

Как показано выше, MXKV теперь активен.

2.1.2 Создание таблицы с столбцом MXKV

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

=# CREATE TABLE data(
    time timestamp with time zone,
    tag_id int,
    kv mxkv_int4
   )
   USING MARS3
   DISTRIBUTED BY (tag_id)
   ORDER BY (time,tag_id);

2.1.3 Определение ключей

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

MXKV предоставляет UDF mxkv_import_keys для определения ключей.

Доступны два метода:

  1. Ручное определение

Предоставьте пример объекта JSON. MXKV автоматически извлечёт и зарегистрирует ключи.

Следующий SQL извлекает и определяет ключи 'a' и 'b':

=# SELECT mxkv_import_keys('{"a": 1, "b": 2}');
 mxkv_import_keys
------------------
 a
 b
(2 rows)
  1. Определение из существующих данных таблицы

Предположим, существует таблица t_json с JSON-столбцом c2:

=# SELECT c2 FROM t_json ;
    c2
----------
 {"k1":1}
 {"k2":2}
(2 rows)

Из результата видно, что c2 содержит ключи k1 и k2.

Используйте mxkv_import_keys для определения ключей из этой таблицы:

=# SELECT mxkv_import_keys('t_json'::regclass, 'c2');
 mxkv_import_keys
------------------
 k1
 k2
(2 rows)

Как показано, передайте имя таблицы и имя столбца в качестве параметров.
Этот метод более удобен и эффективен, если образцы данных уже существуют в другой таблице.

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

После определения ключей вставьте KV-данные:

=# INSERT INTO data VALUES(now(), 1, '{"a":1, "b":2}');
INSERT 0 1

Вставленные KV-данные содержат ранее определённые ключи 'a' и 'b'.

Примечание!
Ключи должны быть определены до вставки. В противном случае возникнет ошибка:
DETAIL: The key is not imported yet HINT: Import the keys with the mxkv_import_keys() function

2.1.5 Чтение значений ключей

Чтение значений ключей из MXKV аналогично JSON и использует оператор ->:

=# SELECT time, tag_id, kv->'a' as a, kv->'b' as b FROM data;
             time              | tag_id | a | b
-------------------------------+--------+---+---
 2021-07-02 13:23:30.405473+00 |      1 | 1 | 2
(1 row)

Извлечённые значения ключей можно использовать как обычные столбцы — для сравнений или соединений с другими таблицами. Например, создайте таблицу data с такой же структурой, как data, вставьте идентичные данные и выполните соединение:

=# SELECT * FROM data, data1 WHERE data.kv->'a' = data1.kv->'a';
             time              | tag_id |        kv        |             time              | tag_id |        kv
-------------------------------+--------+------------------+-------------------------------+--------+------------------
 2021-07-02 13:23:30.405473+00 |      1 | {"a": 1, "b": 2} | 2021-07-02 13:26:31.828685+00 |      1 | {"a": 1, "b": 2}
(1 row)

Примечание!
В MXKV -> и ->> имеют одинаковый эффект.

2.2 Типы данных MXKV

В предыдущем примере используется тип mxkv_int4. Ниже приведено подробное описание поддерживаемых типов данных MXKV:

  1. mxkv_int4: Хранит 32-битные целые числа (int4 / int).
  2. mxkv_float4: Хранит 32-битные числа с плавающей точкой (float4 / real).
  3. mxkv_float8: Хранит 64-битные числа с плавающей точкой (float8 / float / double precision).
  4. mxkv_text: Хранит текстовые строки.

Для mxkv_float4 и mxkv_float8 можно указать количество десятичных знаков. Например:

=# CREATE TABLE data(
    time timestamp with time zone,
    tag_id int,
    kv mxkv_float4(2)
   )
   USING MARS3
   DISTRIBUTED BY (tag_id)
   ORDER BY (time,tag_id);

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

Указание масштаба преобразует внутреннее хранение в целочисленный формат, улучшая сжатие и производительность. Однако допустимый числовой диапазон соответственно уменьшается.

  • mxkv_float4(scale), scale >= 0
    • mxkv_float4(0): [-2147483500, 2147483500]
    • mxkv_float4(2): [-21474835.00, 21474835.00]
    • mxkv_float4(4): [-214748.3500, 214748.3500]
    • ......
  • mxkv_float8(scale), scale >= 0
    • mxkv_float8(0): [-9223372036854775000, 9223372036854775000]
    • mxkv_float4(2): [-92233720368547750.00, 92233720368547750.00]
    • mxkv_float8(4): [-922337203685477.5000, 922337203685477.5000]
    • ......

Примечание!
MXKV поддерживает только плоские структуры ключ-значение. Вложенность и массивы не допускаются.
Для получения дополнительных технических деталей см. блог-пост MXKV.