Расширяемый тип данных: mxkv

Видеоурок по данному курсу включён в [MatrixDB Data Modeling and Spatial-temporal Distribution Model] (https://www.bilibili.com/video/BV133411r7WH?share_source=copy_web)

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

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

Традиционные решения вышеуказанных проблем:

  1. Сериализация нескольких столбцов и хранение в полях переменной длины.
  2. Использование встроенных типов json или jsonb в PostgreSQL.

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

На этом фоне был разработан mxkv — пользовательский тип данных kv, созданный компанией MatrixDB. Подобно формату json, в mxkv имя столбца используется как ключевое значение. Данный тип обеспечивает удобное расширение, повышает производительность запросов и уменьшает занимаемое дисковое пространство.

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

Как использовать

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

Пользовательские типы данных mxkv входят в расширение MatrixTS, поэтому сначала необходимо создать это расширение:

create extension matrixts;

Проверьте, включён ли mxkv:

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

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

Создание таблицы данных и определение столбца mxkv

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

CREATE TABLE data(
    time timestamp with time zone,
    tag_id int,
    kv mxkv_int4
)
Distributed by (tag_id);

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

Перед использованием типа mxkv для оптимизации сжатия и производительности запросов необходимо сначала определить пары «ключ-значение», чтобы заранее задать набор ключей, содержащихся в данных.

mxkv предоставляет пользовательскую функцию mxkv_import_keys для выполнения определения ключей и значений.

Существует два способа определения:

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

Вручную предоставьте примеры kv в формате json, mxkv автоматически извлечёт ключи и завершит определение.

Следующий SQL-запрос извлечёт ключи 'a' и 'b' из json и выполнит их определение:

mxadmin=# select mxkv_import_keys('{"a": 1, "b": 2}');
 mxkv_import_keys
------------------
 a
 b
(2 rows)

Определение на основе существующих таблиц

Имеется существующая таблица t_json, включающая поле c2 типа json:

mxadmin=# select c2 from t_json ;
    c2
----------
 {"k1":1}
 {"k2":2}
(2 rows)

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

Используйте mxkv_import_keys, чтобы выполнить определение на основе данных таблицы:

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

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

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

После определения ключей можно начинать вставку данных kv:

mxadmin=# insert into data values(now(), 1, '{"a":1, "b":2}');
INSERT 0 1

Как показано выше, вставленные данные kv содержат ранее определённые ключи 'a' и 'b'.

Примечание: Ключи в kv должны быть предварительно определены, иначе при вставке возникнет ошибка:

mxadmin=# insert into data values(now(), 1, '{"c":1}');
psql: ERROR:  unknown key "c"
LINE 1: insert into data values(now(), 1, '{"c":1}');
                                          ^
DETAIL:  The key is not imported yet
HINT:  Import the keys with the mxkv_import_keys() function

Чтение содержимого ключей и значений

Содержимое ключей и значений mxkv читается так же, как и json, с использованием символа ->:

mxadmin=# 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, вставьте те же данные и используйте следующий SQL-запрос для соединения:

mxadmin=# 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 аналогичен ->>.

Типы данных

Выше была создана таблица с использованием типа 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: Хранит строковые значения типа text

Типы mxkv_float4 и mxkv_float8 позволяют указывать количество знаков после запятой, например:

CREATE TABLE data(
    time timestamp with time zone,
    tag_id int,
    kv mxkv_float4(2)
)
Distributed by (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 поддерживает только одномерную структуру «ключ-значение» и не допускает вложенности и массивов.