数据反规范化
了解反规范化策略
源数据库中的数据通常是 规范化的。 这意味着列不能有复合值(如数组),实体之间的关系表示为不同表之间的主键到外键的映射。 规范化的数据模型减少了冗余并提高了写查询的数据完整性,但这是以速度为代价的。 另一方面,Redis缓存专注于使读取查询快速,因此RDI提供了数据 反规范化来帮助实现这一点。
嵌套策略
嵌套是RDI用于在源数据库中反规范化多对一关系的策略。它通过将父对象(“一”)表示为包含子对象(“多”)嵌套在父对象的JSON映射属性中的JSON文档来实现这一点。下图显示了子对象嵌套在名为InvoiceLineItems
的映射中的情况:

您可以在子实体的RDI作业中使用nest
块来配置规范化,如下例所示:
source:
server_name: chinook # Optional. Use the value of `debezium.source.topic.prefix` property in Debezium's `application.properties`
schema: public
table: InvoiceLine
output:
- uses: redis.write
with:
nest: # cannot co-exist with other parameters such as 'key'
parent:
# server_name: chinook
# schema: public
table: Invoice
nesting_key: InvoiceLineId # cannot be composite
parent_key: InvoiceId # cannot be composite
path: $.InvoiceLineItems # path must start from document root ($)
structure: map # only map supported for now
on_update: merge # only merge supported for now
data_type: json # only json supported for now
该作业在output
下有一个with
部分,其中包括nest
块。
作业必须在nest
块中包含以下属性:
parent
: 这指定了父实体的RDI数据流。通常,您只需要提供父table
名称,除非您将子实体嵌套在来自不同源数据库的父实体下。如果这样做,则还必须指定server_name
和schema
属性。nesting-key
: 子实体中存储子实体唯一ID(主键)的字段。parent-key
: 父实体中存储父实体唯一ID(外键)的字段。child_key
: 子实体中存储父实体唯一ID(外键)的字段。 只有当子实体的外键字段名称与父实体的不同时,才需要添加此属性。path
: 您想要存储子实体的映射的JSONPath。路径必须以$
字符开头,表示文档根目录。structure
: (可选)子实体的JSON嵌套结构类型。目前,仅支持JSON映射,因此如果提供此属性,则值必须为map
。
使用嵌套时需要注意几个重要事项:
-
当你在任务中指定
nest
时,你还必须在周围的output
块中将data_type
属性设置为json
,并将on_update
属性设置为merge
。 -
对于
nest
输出块,不支持关键表达式。父键始终使用以下模板计算:: nest.child_key.value>: | 例如:
Invoice:InvoiceId:1
-
如果你在
nest
输出块中指定expire
,那么这将设置父对象的过期时间。 -
你只能使用一层嵌套。
-
如果您正在使用PostgreSQL,那么您必须对想要嵌套的所有子表进行以下更改:
ALTER TABLE <TABLE_NAME> REPLICA IDENTITY FULL;
此配置影响写入预写日志(WAL)的信息以及RDI是否可以捕获这些信息。默认情况下,PostgreSQL仅在日志中记录修改的字段,这意味着它可能会省略
parent_key
。这可能会导致目标数据库中Redis键的错误更新。 有关此问题的更多信息,请参阅 Debezium PostgreSQL Connector Documentation。