KLIP 3 — Десериализация и сериализация одиночных полей
Автор: @big-andy-coates | Целевая версия выпуска: 5.3 + 1 | Статус: значения: объединено, ключи: одобрено | Обсуждение: PR #2824
Краткое содержание: Добавить возможность десериализации из примитивных типов, массивов и карт и их сериализацию.
И JSON, и Avro поддерживают сериализацию объектов с несколькими именованными полями. JSON имеет объекты JSON, а Avro — записи Avro.
Оба формата также поддерживают другие типы: JSON поддерживает тип массива и небольшой выбор примитивных типов (Number, String и Boolean); Avro поддерживает типы массивов и карт наряду с более широким диапазоном примитивных типов.
Коллективный термин запись используется для обозначения объектов JSON и записей Avro. Термин не запись используется для обозначения любых других типов.
Строка в KSQL имеет логическую схему, состоящую из нескольких полей. Поля в схеме строки сохраняются либо в ключе, либо в значении базовой записи Kafka. В этом смысле ключ и значение также имеют логическую схему.
Термин схема одного поля используется для описания логической схемы ключа или значения, где схема содержит только одно поле.
Термин верхний уровень используется для описания первой сущности, найденной в сериализованных данных, например, «запись верхнего уровня» будет означать, что сериализованные данные содержат запись с именованными полями, тогда как «число верхнего уровня» будет означать данные, содержащие число JSON или Avro без упаковки записи.
В настоящее время форматы JSON и AVRO в KSQL могут десериализовать только значения записей, то есть те, которые имеют форму объекта JSON или записи Avro. Эти форматы могут десериализовывать типы не записей только в том случае, если эти типы содержатся в качестве поля в типе записи верхнего уровня.
Аналогично, KSQL всегда сериализует поля значений в схеме как поля в схеме типа записи верхнего уровня. Нет поддержки для сериализации схем, содержащих только одно значение поля не записи. Например, если запрос выбирает только одно целочисленное поле INT, оно будет сериализовано внутри записи, его нельзя сериализовать как простое целое число.
С другой стороны, KSQL поддерживает только строковые ключи, то есть тип не записи.
Возможность обрабатывать и создавать как записи, так и типы не записей открывает KSQL для большего количества вариантов использования и является предварительным условием для расширения KSQL до поддержки ключей записей, также известных как структурированные ключи или составные ключи. (Поддержка ключей не записей потребуется, чтобы позволить KSQL поддерживать обратную совместимость с существующими запросами, которые имеют строковые ключи).
Например, учитывая утверждение типа:
CREATE STREAM USERS (NAME STRING) WITH (...);
логическая схема значений имеет только одно поле. KSQL должен иметь возможность считывать данные в Kafka, где значением является анонимная строка верхнего уровня JSON или Avro, а не только запись, содержащая поле NAME.
Учитывая утверждение типа:
CREATE STREAM FOO AS SELECT ID FROM BAR;
Логическая схема значений снова представляет собой только одно поле, скажем, типа INT. Пользователи должны иметь возможность контролировать, будет ли это сериализоваться как именованное поле ID внутри записи или как анонимное число JSON или целое число Avro.
Сериализация (десериализация) схем JSON, содержащих одно поле значения SQL типа ARRAY, MAP, STRUCT или примитивного типа.
Сериализация (десериализация) схем Avro, содержащих одно поле значения SQL типа ARRAY, MAP, STRUCT или примитивного типа.
Сериализация (десериализация) ключей записей и ключей не записей, но только в контексте обеспечения дизайна, который можно расширить, включив такие ключи.
Любая конфигурация и/или синтаксис, используемые для управления сериализацией (десериализацией) схем одного поля.
Обеспечение совместимости с запросами, запущенными в более ранних версиях KSQL, т. е. обеспечение того, чтобы эти запросы продолжали сериализовать схемы одного поля, как они делали ранее.
Это будущая работа.
Другие текущие или будущие форматы. Хотя дизайн должен быть продуман таким образом, чтобы обеспечить совместимость функциональности с будущими форматами, которые может поддерживать KSQL.
Значение/возврат
Работа преимущественно направлена на то, чтобы проложить путь для структурированной работы с ключами, так как этот KLIP является предварительным условием этой работы.
Однако эта функциональность позволит KSQL работать с большим количеством схем значений, открывая KSQL для большего количества вариантов использования.
Публичные API
Новая конфигурация:
ksql.persistence.wrap.single.values: которая предоставляет значение по умолчанию для того, как схемы VALUE с одним полем должны быть десериализованы и сериализованы: true указывает, что значения должны сохраняться в записи; false указывает, что значения должны быть сохранены как анонимные значения.
Значение по умолчанию будет истинным, т. е. значения будут заключены в оболочку по умолчанию. Причины этого выбора:
Этот параметр повлияет на оба оператора C* и C*\AS, если не будет предоставлено явное переопределение.
ksql.persistence.wrap.single.keys: которая предоставляет значение по умолчанию для того, как ключевые схемы с одним полем должны быть десериализованы и сериализованы: true указывает, что ключи должны сохраняться внутри записи; false указывает, что значения должны быть сохранены как анонимные значения.
Значение по умолчанию будет ложным, т.е. ключи будут развёрнуты по умолчанию. Причины такого выбора:
Этот параметр влияет на оба оператора C* и C*\AS, если не предоставляется явное переопределение.
Примечание: эта новая конфигурация будет добавлена как часть будущей работы со структурированными ключами.
Синтаксис SQL
Пользователи могут переопределить настроенные по умолчанию параметры и контролировать, как однополевые ключевые и ценностные схемы сериализуются, предоставляя следующие свойства предложения WITH в любом операторе C* или C*AS.
WRAP_SINGLE_VALUE: логическое свойство, которое переопределит конфигурацию ksql.persistence.wrap.single.values.
WRAP_SINGLE_KEY: логическое свойство, которое переопределит конфигурацию ksql.persistence.wrap.single.keys.
Примечание: будет добавлено как часть будущей работы со структурированными ключами.
WRAP_SINGLE_FIELDS: логическое свойство, являющееся сокращением для установки как WRAP_SINGLE_KEY, так и WRAP_SINGLE_VALUE.
Примечание: будет добавлено как часть будущей работы со структурированными ключами.
Дизайн
CREATE STREAM и CREATE TABLE
Операторы C* будут по умолчанию захватывать значения ksql.persistence.wrap.single.keys и ksql.persistence.wrap.single.values. Пользователи могут переопределить эти настройки, предоставив любое из семейства свойств предложения WITH WRAP_SINGLE_XXX. Эти настройки будут храниться как часть метаданных созданного источника. Эти настройки контролируют, как данные в теме источника должны быть десериализированы последующими запросами. Предоставление любой из этих настроек приведёт к ошибке, если связанная схема(ы) будет многополевой.
Например:
-- Default config: ksql.persistence.wrap.single.values=false
-- creates a stream, picking up the system default of not wrapping
-- the serialized value is expected to not be wrapped.
-- if the serialized value is wrapped it will likely result in a deserialization error.
CREATE STREAM IMPLICIT_SOURCE (ID INT) WITH (...);
-- override 'ksql.persistence.wrap.single.values' to true
-- the serialized value is expected to not be
``` ### Создание потоков и таблиц с помощью CREATE STREAM AS и CREATE TABLE AS
Операторы C*AS по умолчанию фиксируют значения `ksql.persistence.wrap.single.keys` и `ksql.persistence.wrap.single.values`.
Пользователи могут переопределить эти настройки, указав любое из свойств предложения `WITH` семейства `WRAP_SINGLE_XXX`.
Эти параметры будут сохранены как часть метаданных созданного источника.
Данные настройки контролируют сериализацию данных в источнике и их десериализацию последующими запросами.
Если указать любой из этих параметров, то при наличии многопольного связанного формата возникнет ошибка.
Например:
```sql
-- Конфигурация по умолчанию: ksql.persistence.wrap.single.values=false
-- Создаёт поток, используя системную настройку не обёртывать
-- Сериализованные значения в базовой теме не будут обёрнуты.
CREATE STREAM IMPLICIT_SOURCE AS SELECT ID FROM S;
-- Переопределяет 'ksql.persistence.wrap.single.values' на true
-- Сериализованные значения будут обёрнуты.
CREATE STREAM EXPLICIT_SOURCE WITH(WRAP_SINGLE_VALUE=true) AS SELECT ID FROM S;
-- Возникает ошибка, так как схема значений многополевая
CREATE STREAM BAD_SOURCE WITH(WRAP_SINGLE_VALUE=true) AS SELECT ID, COST FROM S;
-- [В будущем, со структурированными ключами]
-- Явно устанавливает оба параметра на false.
-- Сериализованные ключи и значения не будут обёрнуты.
CREATE SOURCE SK_SOURCE WITH(WRAP_SINGLE_FIELDS=false) AS SELECT ID KEY, NAME STRING FROM S;
Запросы INSERT не создают собственные источники. Они используют параметры сериализации приёмника.
Например,
-- Будет использовать параметры сериализации SINK для определения, должны ли значения быть обёрнутыми или нет.
INSERT INTO SINK SELECT ID FROM SOURCE;
-- Также будет использовать параметры сериализации `SINK`, хотя в этом случае они будут обёрнуты, поскольку являются многопольными.
INSERT INTO SINK SELECT ID, NAME FROM SOURCE;
Запросы INSERT VALUES не создают собственные источники. Они используют параметры сериализации приёмника.
-- Будет использовать параметры сериализации SINK, чтобы определить, должны ли однополевые схемы быть обёрнутыми или нет.
INSERT INTO SINK (ID) VALUES (10);
-- Также будет использовать параметры сериализации `SINK`, хотя в этом случае они будут обёрнуты, поскольку являются многопольными.
INSERT INTO SINK VALUES (10, 'bob');
Тесты будут добавлены для покрытия всех допустимых комбинаций и перестановок следующих измерений:
ksql.persistence.wrap.single.keys
: true и falseksql.persistence.wrap.single.values
: true и falseWRAP_SINGLE_KEY
: true и falseWRAP_SINGLE_VALUE
: true и falseWRAP_SINGLE_FIELDS
: true и falseWRAP_SINGLE_KEY
: true и falseWRAP_SINGLE_VALUE
: true и falseWRAP_SINGLE_FIELDS
: true и falseСначала это будет сделано только для значений. Поддержка ключей будет добавлена в рамках работы над структурированными ключами.
Примечание: объединение WRAP_SINGLE_FIELDS
с WRAP_SINGLE_KEY
или WRAP_SINGLE_VALUE
должно привести к ошибке дублирования настроек.
Также будут добавлены тесты JSON, чтобы убедиться, что новые конфигурации можно установить с помощью команды SET
и они выбираются должным образом. Документация обновлена
config-reference.rst
будут добавлены следующие две настройки:.. _ksql-persistence-wrap-single-keys:
---------------------------------
ksql.persistence.wrap.single.keys
---------------------------------
Устанавливает значение по умолчанию для свойства ``WRAP_SINGLE_KEY``, если оно не указано явно в операторах :ref:`CREATE TABLE <create-table>`, :ref:`CREATE STREAM <create-stream>`, :ref:`CREATE TABLE AS SELECT <create-table-as-select>` или :ref:`CREATE STREAM AS SELECT <create-stream-as-select>`.
Эту настройку можно переключить с помощью команды `SET`:
.. code:: sql
SET 'ksql.persistence.wrap.single.keys'='true';
Для получения дополнительной информации см. разделы :ref:`CREATE TABLE <create-table>`, :ref:`CREATE STREAM <create-stream>`, :ref:`CREATE TABLE AS SELECT <create-table-as-select>` и :ref:`CREATE STREAM AS SELECT <create-stream-as-select>`.
.. note:: Эта настройка не влияет на форматы, которые не поддерживают какой-либо внешний объект или запись. Например, ``DELIMITED``.
.. _ksql-persistence-wrap-single-values:
-----------------------------------
ksql.persistence.wrap.single.values
-----------------------------------
Устанавливает значение по умолчанию для свойства ``WRAP_SINGLE_VALUE``, если оно не указано явно в операторах :ref:`CREATE TABLE <create-table>`, :ref:`CREATE STREAM <create-stream>`, :ref:`CREATE TABLE AS SELECT <create-table-as-select>` или :ref:`CREATE STREAM AS SELECT <create-stream-as-select>`.
Эту настройку можно переключить с помощью команды `SET`:
.. code:: sql
SET 'ksql.persistence.wrap.single.values'='false';
Для получения дополнительной информации см. разделы :ref:`CREATE TABLE <create-table>`, :ref:`CREATE STREAM <create-stream>`, :ref:`CREATE TABLE AS SELECT <create-table-as-select>` и :ref:`CREATE STREAM AS SELECT <create-stream-as-select>`.
.. note:: Эта настройка не влияет на форматы, которые не поддерживают какой-либо внешний объект или запись. Например, ``DELIMITED``.
CREATE TABLE
и CREATE STREAM
в syntax-reference.rst
получат обновлённый раздел свойств, который включает следующие строки: +=========================+========================================================================================================+
| WRAP_SINGLE_KEY | Управляет тем, как ключи десериализуются, когда схема ключа содержит только одно поле. |
| | |
| | Настройка управляет тем, как KSQL будет десериализовать ключ записей в предоставленной ``KAFKA_TOPIC``.|
| | Если установлено значение ``true``, KSQL ожидает, что поля (поля) будут сериализованы как именованные поля|
| | внутри записи. |
| | Если установлено значение ``false`` и ключ имеет схему с одним полем, KSQL ожидает, что поле будет |
| | сериализовано как анонимное значение. |
| | Установка значения ``false``, когда ключ является многополевой схемой, приведёт к ошибке |
| | |
| | Если не указано, используется системное значение по умолчанию, определённое :ref:`ksql-persistence-wrap-single-keys`|
| | и по умолчанию равное ``false``. |
| | |
| | Примечание: установка этого свойства для форматов, которые не поддерживают перенос, например `DELIMITED`,|
| | приведёт
``` **JSON**
Формат JSON поддерживает значения JSON.
Формат JSON поддерживает все типы данных KSQL (см. раздел «Типы данных»). Поскольку сам JSON не поддерживает тип map, KSQL сериализует MAP как объекты JSON. Из-за этого формат JSON может поддерживать только объекты MAP со строковыми ключами.
Сериализованный объект должен быть строкой, сериализованной в Kafka и содержащей допустимое значение JSON. Формат поддерживает объекты JSON и примитивы верхнего уровня, массивы и карты. Подробнее см. ниже.
**Объекты JSON**
Значения, которые являются объектами JSON, вероятно, наиболее распространены.
Например, учитывая оператор KSQL:
.. code:: sql
CREATE STREAM x (ID BIGINT, NAME STRING, AGE INT) WITH (VALUE_FORMAT='JSON', ...);
И значение JSON:
.. code:: json
{
"id": 120,
"name": "bob",
"age": "49"
}
KSQL десериализует поля объекта JSON в соответствующие поля потока.
*Примечание:* KSQL имеет специальную обработку схем с одним полем. KSQL поддерживает схемы с одним полем, которые сериализуются как именованное поле внутри объекта JSON или анонимное значение JSON. По умолчанию KSQL ожидает, что исходные данные будут иметь ключи с одним полем, которые были сериализованы как анонимные значения, а значения — как объекты JSON. Аналогично, по умолчанию KSQL сериализует выходные данные таким же образом. Обработкой однопольных схем KSQL можно управлять. Для получения дополнительной информации см. раздел single_field_wrapping.
**Примитивы верхнего уровня, массивы и карты**
Формат JSON поддерживает чтение и запись примитивов верхнего уровня, массивов и карт.
Например, если задан оператор KSQL только с одним полем в схеме значений и свойством WRAP_SINGLE_VALUE, установленным в false:
.. code:: sql
CREATE STREAM x (ID BIGINT) WITH (VALUE_FORMAT='JSON', WRAP_SINGLE_VALUE=false, ...);
И значением JSON:
.. code:: json
10
KSQL может десериализовать значения в поле ID потока.
При сериализации данных с одним полем KSQL может сериализовать поле как анонимное значение, если для WRAP_SINGLE_VALUE установлено значение false, например:
.. code:: sql
CREATE STREAM y WITH (WRAP_SINGLE_VALUE=false) AS SELECT id FROM x;
Десериализация схем с одним ключевым полем также может контролироваться через свойство WRAP_SINGLE_KEY. Однако по умолчанию для схем с одним ключом используются анонимные значения.
Для получения дополнительной информации см. раздел ksql_single_field_wrapping.
----
**Avro**
Формат AVRO поддерживает двоичную сериализацию Avro всех типов данных KSQL, включая записи и примитивы верхнего уровня, массивы и карты.
Формату требуется, чтобы KSQL был настроен на хранение и извлечение схем Avro из |sr-long|. Для получения дополнительной информации см. раздел install_ksql-avro-schema.
**Записи Avro**
Записи Avro могут быть десериализованы в соответствующие схемы KSQL.
Например, задав оператор KSQL вида:
.. code:: sql
CREATE STREAM x (ID BIGINT, NAME STRING, AGE INT) WITH (VALUE_FORMAT='JSON', ...);
И запись Avro, сериализованная со схемой:
.. code:: json
{
"type": "record",
"namespace": "com.acme",
"name": "UserDetails",
"fields": [
{ "name": "id", "type": "long" },
{ "name": "name", "type": "string" }
{ "name": "age", "type": "int" }
]
}
KSQL будет десериализовывать поля записи Avro в соответствующие поля потока. Обработка однополевых схем может контролироваться. Для получения дополнительной информации см. раздел «single_field_wrapping».
-------------------------------------
Основные примитивы, массивы и карты
-------------------------------------
Формат Avro поддерживает чтение и запись основных примитивов, массивов и карт.
Например, если дано выражение KSQL с единственным полем в схеме значений и свойством «WRAP_SINGLE_VALUE», установленным в «false»:
.. код:: sql
CREATE STREAM x (ID BIGINT) WITH (VALUE_FORMAT='AVRO', WRAP_SINGLE_VALUE=false, ...);
И значение Avro, сериализованное со схемой:
.. код:: json
{
"type": "long"
}
KSQL может десериализовать значения в поле «ID» потока.
При сериализации данных с одним полем KSQL может сериализовать поле как анонимное значение, если для «WRAP_SINGLE_VALUE» установлено значение «false», например:
.. код:: sql
CREATE STREAM y WITH (WRAP_SINGLE_VALUE=false) AS SELECT id FROM x;
Сериализация однополевых ключевых схем также может управляться через свойство «WRAP_SINGLE_KEY». Однако следует отметить, что по умолчанию для однополевых ключевых схем используются анонимные значения.
Для получения дополнительной информации см. «ksql_single_field_wrapping».
=========================
Управление сериализацией
=========================
KSQL предлагает несколько механизмов управления сериализацией и десериализацией.
Основной механизм заключается в выборе формата сериализации при создании потока или таблицы и указании «VALUE_FORMAT» в предложении «WITH».
.. код:: sql
CREATE TABLE x (F0 INT, F1 STRING) WITH (VALUE_FORMAT='JSON', ...);
Дополнительную информацию о форматах, поддерживаемых KSQL, см. в разделе «ksql_formats».
KSQL предоставляет некоторую дополнительную конфигурацию, позволяющую управлять сериализацией:
.. _single_field_wrapping
-------------------------
Однополевое (раз)обёртывание
-------------------------
.. note:: Формат «DELIMITED» не затрагивается однополевой распаковкой.
Управление десериализацией одиночных полей
==========================================
Когда KSQL десериализует запись Kafka в строку, ключ десериализуется в поля ключа, а значение записи десериализуется в поля значения.
По умолчанию KSQL ожидает, что любой ключ с однополевой схемой будет сериализован как анонимное значение, а не как именованное поле внутри записи, как это было бы в случае наличия нескольких полей.
И наоборот, по умолчанию KSQL ожидает, что любое значение с однополевой схемой было сериализовано как именованное поле в записи.
Значения по умолчанию для ключей и значений с одним полем различаются, поскольку они отражают наиболее распространённые варианты использования KSQL. Кроме того, любое изменение ключевой схемы, скорее всего, станет критическим изменением для любой существующей системы, так как оно изменит разделение данных. Поэтому эволюция ключевых схем обычно не вызывает беспокойства.
Если взять схему значений в качестве примера, значение с несколькими полями может выглядеть следующим образом в JSON:
.. код:: json
{
"id": 134,
"name": "John"
}
Если значение имело только поле «id», KSQL всё равно ожидал бы, что значение будет сериализовано в виде именованного поля, например:
.. код:: json
{
"id": 134
}
Если ваши данные содержат только одно поле, и это поле не заключено в объект JSON (или запись Avro при использовании формата «AVRO»), вы можете использовать свойство «WRAP_SINGLE_VALUE» в предложении «WITH» ваших выражений :ref:`CREATE TABLE <create-table>` или :ref:`CREATE STREAM <create-stream>`. Установка свойства в «false» сообщит KSQL, что значение не упаковано, то есть пример выше будет числом JSON:
.. код:: json
134
Например, следующее создаёт таблицу, в которой значения в базовой теме были сериализованы как анонимный номер JSON:
.. код:: sql
CREATE TABLE x (ID INT) WITH (WRAP_SINGLE_VALUE=false, ...); **Контроль сериализации одиночных полей**
WRAP_SINGLE_FIELDS — это сокращение для установки обоих свойств.
Если в операторе явно не заданы ключ или значение, будут использоваться системные значения по умолчанию, определённые ksql.persistence.wrap.single.keys и ksql.persistence.wrap.single.values. Эти системные значения также можно изменить. Для получения дополнительной информации см. документацию ksql-persistence-wrap-single-keys и ksql-persistence-wrap-single-values.
**Сериализация отдельных полей при работе с KSQL**
Когда KSQL сериализует строку в запись Kafka, поле ключа сериализуется в ключ записи, а любое поле значения — в значение записи.
По умолчанию, если ключ имеет только одно поле, KSQL будет сериализовать это поле как анонимное значение, а не как именованное поле в записи, как это было бы, если бы полей было несколько.
И наоборот, если значение имеет только одно поле, KSQL сериализует это поле как именованное поле внутри записи.
Значения по умолчанию для однополевых ключей и значений различаются, поскольку они отражают наиболее распространённые варианты использования KSQL. Кроме того, любое изменение схемы ключа, скорее всего, приведёт к нарушению работы любой существующей системы, так как оно изменит разделение данных. Поэтому эволюция схем ключей обычно не вызывает беспокойства.
Рассмотрим в качестве примера следующие операторы:
.. code:: sql
CREATE STREAM x (f0 INT, f1 STRING) WITH (VALUE_FORMAT='JSON', ...);
CREATE STREAM y AS SELECT f0 FROM x;
Второй оператор определяет поток с единственным полем в значении, названным f0.
При записи результата в Kafka KSQL по умолчанию сохранит единственное поле как именованное поле объекта JSON (или записи Avro, если используется формат AVRO):
.. code:: json
{
"F0": 10
}
Если требуется, чтобы значение было сериализовано как анонимное, например:
.. code:: json
10
Можно использовать свойство WRAP_SINGLE_VALUE в своём операторе. Например:
.. code:: sql
CREATE STREAM y WITH(WRAP_SINGLE_VALUE=false) AS SELECT f0 FROM x;
Аналогично можно использовать свойство WRAP_SINGLE_KEY для управления сериализацией ключей с одиночными полями или использовать WRAP_SINGLE_FIELDS в качестве сокращения для настройки обоих.
Если оператор явно не устанавливает перенос ключа или значения, используются системные значения по умолчанию, определённые ksql.persistence.wrap.single.keys и ksql.persistence.wrap.single.values. Их также можно изменить. Дополнительную информацию см. в документации ksql-persistence-wrap-single-keys и ksql-persistence-wrap-single-values. С (С РАСПОЛОЖЕНИЕМ ОДИНОЧНОГО КЛЮЧА = истина) КАК ВЫБРАТЬ ИДЕНТИФИКАТОР ИЗ S;
-- приводит к ошибке, так как схема значения является многополевой
СОЗДАТЬ ПОТОК BAD_SINK С (РАСПОЛОЖЕНИЕМ ОДИНОЧНОГО ЗНАЧЕНИЯ = истина) КАК ВЫБРАТЬ ИДЕНТИФИКАТОР, СТОИМОСТЬ ИЗ S;
* Подходящие детали будут добавлены в changelog.rst.*
# Последствия для совместимости
Тесты уже проведены, чтобы гарантировать, что это изменение не изменит схему или формат любых внутренних тем.
Устаревшие запросы, то есть те, которые были запущены в предыдущих версиях KSQL, имеют развёрнутые строковые ключи и оборачивают значения с однополевыми схемами.
Чтобы сохранить обратную совместимость, это должно продолжаться после завершения предложенной работы.
Обратная совместимость схемы значений поддерживается по умолчанию для ksql.persistence.wrap.single.values = истина. Это означает, что устаревшие запросы будут продолжать оборачивать однополевые схемы значений.
Обратная совместимость схем ключей поддерживается по умолчанию для ksql.persistence.wrap.single.keys = ложь. Это означает, что устаревшие запросы не будут оборачивать однополевые ключевые схемы.
## Последствия для производительности
Решение о десериализации и сериализации значений либо в обёрнутом, либо в развёрнутом виде принимается только при инициировании запроса. После этого классы serde работают с фиксированной схемой. Поэтому не должно быть никаких последствий для производительности, кроме стоимости сериализации и десериализации оболочки записи, если пользователь настроил запрос на их использование.
## Последствия для безопасности
Нет.
# Отклоненные альтернативы
## Умные десериализаторы
Вместо того чтобы контролировать десериализацию обёрнутых и развёрнутых однополевых схем с помощью семейства свойств WRAP_SINGLE_XXX, можно почти сделать так, чтобы десериализаторы могли определять во время выполнения и для каждой записи отдельно, содержит ли сериализованные данные анонимное значение или одно поле внутри записи.
Например, рассмотрим:
```sql
СОЗДАТЬ STREAM FOO (ИДЕНТИФИКАТОР INT) С (...);
Логическая схема значений содержит одно целочисленное поле ID.
Десериализатор JSON сможет обрабатывать оба следующих значения JSON:
{
"ID": 10
}
и
10
Поскольку он может проверять данные во время выполнения.
Аналогично, десериализатор Avro может проверить схему полученных данных, чтобы определить, получает ли он запись Avro с одним целочисленным полем ID.
Этот подход имеет преимущество в том, что пользователям KSQL не нужно знать или беспокоиться о том, являются ли их исходные данные обёрнутыми или развёрнутыми. Это большая победа! К сожалению, за это приходится платить: существует множество областей, где выбор между обработкой данных как анонимного однополевого или обёрнутого именованного поля становится неоднозначным.
JSON сталкивается с двусмысленностью, когда ему предоставляется один MAP или STRUCT, оба из которых сериализуются как объекты JSON, и без схемы трудно понять, является ли полученный объект JSON обёрнутым полем или просто полем.
AVRO лучше, но всё ещё борется со STRUCT.
Десериализаторы могут пойти дальше, проверяя, могут ли значения быть приведены к любой схеме, но это добавляет накладные расходы, и всё ещё существуют случаи, особенно при наличии нулевых значений, когда есть пограничные случаи, когда просто неясно, каким образом должен действовать десериализатор.
Эта двусмысленность является причиной того, что эта альтернатива была отклонена в пользу более интуитивного и конкретного поведения.
На самом деле было предложено две альтернативы, в которых свойства WRAP_SINGLE_XXXX рассматривались как унаследованные в запросах C*:
В одном случае свойство рассматривалось как флаг предпочтения, который контролировал, как будет десериализована и сериализована однополевая схема. Флаг всегда наследовался, даже если промежуточные запросы имели многополевые схемы.
В другом случае WRAP_SINGLE_XXX не разрешалось использовать в операторах C* с многополевыми операторами и неявно устанавливалось в истину в многополевых операторах C*.
Первый был отклонён, поскольку описанный выше подход проще.
Второй был отклонён, потому что это означало, что конечный запрос с однополевой схемой... Будет происходить перенос, даже если в исходных операторах C* явно указано «не переносить», системное значение по умолчанию было «не переносить» и промежуточные запросы явно не изменяли перенос, если схема любого промежуточного запроса была многополевой.
WRAP_SINGLE_XXX
на два свойства: одно для десериализации и одно для сериализации.Поскольку текущее семейство свойств предложения WITH
WRAP_SINGLE_XXXX
управляет как десериализацией, так и сериализацией схем с одним полем, невозможно иметь оператор C*, где значение будет десериализовано без переноса, но последующие
запросы будут сериализовать схемы с одним полем с переносом, или наоборот.
Альтернативой может быть разделение WRAP_SINGLE_XXXX
(и соответствующих системных свойств) на
свойства, специфичные для десериализации и сериализации.
Здесь возникает проблема с именованием. Но для аргументации давайте продолжим:
WRAPPED_SINGLE_VALUES
, чтобы контролировать десериализацию, как в «отдельные значения заключены в перенос».WRAP_SINGLE_VALUE
, чтобы управлять сериализацией, как в «пожалуйста, заключайте отдельные значения в перенос».Хотя имена не так важны. Переработав пример, вы получите что-то вроде:
-- Default config: ksql.persistence.deserialization.wrapped.single.value=false
-- Default config: ksql.persistence.serialization.wrap.single.value=false
-- создаёт поток:
-- WRAPPED_SINGLE_VALUES: указывает, что исходные данные имеют незаключённые в перенос значения
-- WRAP_SINGLE_VALUE: указывает, что последующие запросы будут заключать в перенос по умолчанию
CREATE STREAM UNWRAPPED_EXPLICIT_SOURCE (ID INT) WITH (WRAPPED_SINGLE_VALUES=false, WRAP_SINGLE_VALUE=true, ...);
-- создаёт поток:
-- ksql.persistence.deserialization.wrapped.single.value указывает, что исходные данные не заключены в перенос
-- ksql.persistence.serialization.wrap.single.values указывает, что последующие запросы не будут заключать в перенос значения по умолчанию
CREATE STREAM IMPLICIT_SOURCE (ID INT) WITH (...);
-- создаёт поток:
-- с несколькими полями:, поэтому KSQL знает, что они будут заключены в перенос.
-- WRAP_SINGLE_VALUE: указывает, что последующие запросы НЕ будут заключать в перенос значения по умолчанию
CREATE STREAM MULTI_FIELD_SOURCE (ID INT, NAME STRING) WITH (WRAP_SINGLE_VALUE=false, ...);
-- приведёт к ошибке, поскольку `WRAPPED_SINGLE_VALUES` не может быть `false` для схемы с несколькими полями.
CREATE STREAM BAD_SOURCE (ID INT, NAME STRING) WITH (WRAPPED_SINGLE_VALUES=false, ...);
-- KSQL знает, что исходные данные заключены в перенос, потому что источник помечен как таковой
-- сериализованное значение будет заключено в перенос из-за унаследованных свойств
-- последующие запросы будут заключать значения в перенос по умолчанию из-за унаследованных свойств
CREATE STREAM A AS SELECT ID FROM EXPLICIT_SOURCE;
-- KSQL знает, что исходные данные заключены в перенос, потому что источник помечен как таковой
-- сериализованные значения не будут заключены в перенос из-за предложения with
-- последующие запросы не будут заключать значения в перенос по умолчанию, из-за предложения with
CREATE STREAM B WITH(WRAP_SINGLE_VALUE=false) AS SELECT ID FROM EXPLICIT_SOURCE;
-- KSQL знает, что исходные данные не заключены в перенос, потому что источник помечен как таковой и имеет схему с одним полем
-- сериализованное значение не будет заключено в перенос из-за унаследованных свойств
-- последующие запросы не будут заключать значения в перенос по умолчанию из-за унаследованных свойств
CREATE STREAM C AS SELECT ID FROM IMPLICIT_SOURCE;
-- KSQL знает, что исходные данные не заключены в перенос, потому что источник помечен как таковой и имеет схему с одним полем
-- сериализованное значение будет заключено в перенос из-за предложения with
-- последующие запросы будут заключать значения в перенос по умолчанию из-за предложения with
CREATE STREAM D WITH(WRAP_SINGLE_VALUE=true) AS SELECT ID FROM IMPLICIT_SOURCE;
-- KSQL знает, что исходные данные заключены в перенос, так как у него несколько полей
-- сериализованное значение будет заключено в перенос, поскольку у него есть несколько полей
-- последующие запросы не будут заключать одиночные значения в перенос по умолчанию из-за унаследованных свойств
CREATE STREAM E AS SELECT ID, NAME FROM MULTI_FIELD_SOURCE;
-- KSQL знает, что исходные данные заключены в перенос, так как у него несколько полей
-- сериализованное значение будет заключено в перенос, поскольку у него есть несколько полей
-- последующие запросы будут заключать одиночные значения в перенос по умолчанию из-за предложения with
CREATE STREAM F WITH(WRAP_SINGLE_VALUE=true) AS SELECT ID,
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )