探索 Airbyte 的增量数据同步

为了从数据集成策略中获得最大价值,您需要跨多个系统同步查看数据。数据同步涉及将数据从源系统复制到目标系统,在目标系统中,通过将源系统上的修改持续同步到目标系统来保持数据一致性。可以通过多种方式完成数据同步,包括:完全复制、增量复制或更改数据捕获 (CDC) 复制。

这是探索 Airbyte 同步模式的三部分系列教程中的第二个教程。本系列的目的是为您提供分步说明,以便您可以亲自了解 Airbyte 复制的数据在不同同步模式下的外观,并帮助您了解每种同步模式在后台的工作方式。如果您尚未这样做,我建议您先阅读探索 Airbyte 的完全刷新数据同步(本系列的上一篇文章),然后再继续本教程。

本系列的第二个教程重点介绍 Airbyte 的增量同步模式。在本教程中,您将:

  • 了解什么是增量同步及其工作原理。
  • 了解增量同步何时可能是一个不错的选择。
  • 了解什么是游标,以及为什么增量同步需要游标
  • 了解为什么重复数据删除需要主键
  • 创建 Airbyte 源连接器以从源数据库读取数据。
  • 创建 Airbyte 目标连接器以将数据写入目标数据库。
  • 使用增量同步 - 追加同步模式探索增量数据库复制
  • 使用增量同步 - 重复数据删除历史记录同步模式探索增量数据库复制。
  • 检查复制到目标数据库的原始 JSON 数据
  • 检查从原始 JSON 创建的规范化数据
  • 查看 Airbyte 用于规范化 JSON 数据的 SQL 代码
  • 查看源数据库上的插入更新删除操作如何反映在目标中。
i️如果您不确定哪种复制模式最适合您的使用案例,在继续本教程之前,您可能有兴趣阅读   Airbyte 的复制模式概述。

软件版本

本教程编写于 2022 年 <> 月,由于 Airbyte 的快速变化性质,将来可能会变得不那么重要。本教程中的示例使用了以下工具/版本:

  • macOS:12.3.1
  • Docker desktop: 4.10.1 (82475)
  • Docker compose:1.29.2
  • Debezium/Postgres:Docker image tag: 13
  • Airbyte 开源(参见:部署 Airbyte):0.39.41-alpha

Airbyte的ELT方法简介

当 Airbyte 将数据从源复制到目标时,它首先将数据复制到“原始”表中。然后,如果启用了规范化,则此数据将由目标中的 Airbyte 触发的 SQL 命令进行转换。Airbyte 利用 dbt 创建用于规范化数据的 SQL,并利用公用表表达式(或 CTE)将 SQL 分解为更模块化和易于理解的部分。在本教程的后面部分,您将探索用于规范化的低级别 SQL,并将查看目标数据库中的原始表和规范化表。

下图在高级别上显示了 Airbyte 的 ELT 方法:

探索 Airbyte 的增量数据同步_第1张图片

什么是增量同步

增量同步是一种复制方法,可有效地使源和目标保持同步。与完全刷新数据同步一样,同步操作会定期从源执行到目标,同步操作的频率由同步计划定义。但是,与完全刷新同步相反,只有自上次同步以来发生的更改才会从源复制到目标 - 换句话说,不会重新复制目标中已有的任何数据。

它是如何工作的

Airbyte 的增量同步在概念上可以被认为是一个周期性执行同步操作的循环。此循环的每次迭代仅 r包含自上次执行此同步循环以来在源系统中插入或更新的记录。这比在每次迭代时复制整个数据集要高效得多,后者是完全刷新同步的行为。

增量同步模式有什么区别

在高级别上,增量同步 - 追加同步模式会产生最终规范化表,其中包含已在源上插入或更新并同步到目标的每条记录的历史副本。如果记录已多次更新和同步,则会导致最终规范化表中出现多个条目。

另一方面,增量同步 - 重复数据删除历史记录同步模式会生成两个规范化的目标表。其中一个表是历史记录表(也称为 scd 表,指的是缓慢变化的维度),其中包括每条记录的历史版本,其中包括每条记录的开始日期和结束日期。另一个表是重复数据删除表,其中包含每条记录的单个副本。

什么是游标

在给定的同步迭代中仅发送更新或新插入的记录需要跟踪在以前的迭代中发送了哪些记录。游标用于此目的,可以将其视为指向已复制的最新记录的指针。在新的同步迭代期间选择要复制的记录时,Airbyte 将游标值作为源系统上查询的一部分包括在内,以便仅从源中选择比游标更新的记录(即自上次同步以来的新记录或更新的记录)并将其发送到目标。

在本教程中,源数据库包含包含名为 updated_at 的字段的记录,该字段存储插入或更新每条记录的最近时间。这用作光标字段。换句话说,Airbyte 将存储在给定同步中看到的最大updated_at值,然后在后续的同步迭代中,通过将游标值作为查询的一部分来检索已在源上插入的新记录或已更新的记录。在查询中包含游标会将响应限制为仅updated_at值大于或等于上一次同步的最大值updated_at值的记录。

i️ 有关使用游标从源数据库中选择数据的查询的实现中考虑的设计决策和权衡的更多详细信息,请参阅有关   Airbyte SQL 源游标的讨论。

游标的持久化方式和位置

Airbyte 协议指定 Airbyte 源应发出 AirbyteStateMessage。此消息包括最近发出的游标的值以及其他状态信息。最终,Airbyte 将此状态(StatePersistence.java)保存到内部 Postgres 数据库中。如果您想自己查看此数据库,可以按如下方式登录:

docker exec -ti airbyte-db psql -U docker -d airbyte

可以使用以下命令查看状态数据库的内容:

SELECT * FROM state;

哪个应该使用类似于下面给出的表格来响应(请注意,为了简洁起见,本文中的响应是缩写的):

 
  
  1. id | connection_id | state | created_at | updated_at | stream_name | namespace | type

  2. --------------------------------------+--------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------+-------------------------------+-------------+-----------+--------

  3. 884a10a7-1c58-4456-af44-c617eec0c1fb | 78cb42b9-e857-4f93-b159-e590ec31d287 | {"state": {"cdc": false, "streams": [{"cursor": "2022-09-02T07:55:58.324989", "stream_name": "table_one", "cursor_field": ["updated_at"], "stream_namespace": "public"}]}} | 2022-09-01 16:52:44.619871+00 | 2022-09-02 07:59:27.304753+00 | | | LEGACY

为什么以及何时需要主键

在源系统上插入或更新的记录在同步操作期间由 Airbyte 复制到目标,并最初存储在原始数据表中。如果给定文档多次更新和同步,则原始数据表将具有该记录的多个条目(如本文后面的动手深入探讨所示)。

如果 Airbyte 用户选择了增量同步 - 重复数据删除历史记录同步模式,则必须对数据进行重复数据删除,以便源表中的单个条目仅导致最终规范化重复数据删除目标表中的单个相应条目,即使原始和历史数据表中可能会出现与该记录对应的多个版本。Airbyte 使用主键字段仅从历史记录表中选择给定记录的最新版本以包含在最终的重复数据删除表中,并且不包括该记录的所有其他历史版本。

另一方面,由于增量同步 - 追加同步模式不执行任何重复数据删除,因此不需要定义主键。

何时使用增量同步

假设您的数据具有合适的游标字段,并且(对于重复数据删除模式)您具有合适的主键,那么 Airbyte 的增量同步模式可能适合您的数据复制需求。但是,有一些限制需要注意:

  • 删除操作未正确传播。如果您希望传播删除,则更改数据捕获 (CDC) 可能是更合适的同步方法。或者,软删除可能满足你的要求 - 但对此的详细讨论超出了本教程的范围。
  • 如果在源系统上插入或更新记录时未正确更新其游标字段值,则可能无法将其复制到目标数据库。但是,有一些技术可以在修改时自动更新时间戳,您将在本文中学习。
  • 如果在同步迭代之间多次修改记录,则只会将同步时记录的状态复制到目标。不会记录其他中间状态。
  • 目前,只有支持 dbt/SQL 规范化的目标才支持增量同步。

增量追加限制和增量重复数据删除历史记录限制文档中更详细地描述了这些限制。

启动 Postgres 源和目标

上面的讨论简要概述了增量同步模式的工作原理。本文的其余部分重点介绍增量数据库复制期间幕后发生的情况。

如果您已完成本系列中的上一个教程,则可能已经为 Postgres 源和 Postgres 目标运行了容器。如果是这种情况,则可以重复使用这些容器,并可以跳到下一部分。

i️ 本教程中的示例以新的/空的 Postgres 容器的形式提供,但并不要求源数据库和目标数据库为空。

在本地主机上启动在端口 2000 上运行的源 Postgres 容器,如下所示:

 
  
  1. docker run --rm --name airbyte-source -e POSTGRES_PASSWORD=password -p 2000:5432 -d debezium/postgres:13

在本地主机上启动在端口 3000 上运行的目标 Postgres 容器,如下所示:

 
  
  1. docker run --rm --name airbyte-destination -e POSTGRES_PASSWORD=password -p 3000:5432 -d debezium/postgres:13

在 Airbyte 中定义源和目标

实例化 Postgres 源连接器

通过单击“+ 新建源”创建新数据源,如下所示。

探索 Airbyte 的增量数据同步_第2张图片

然后选择 Postgres 作为源,如下所示:

探索 Airbyte 的增量数据同步_第3张图片

 并定义一个名为增量源的连接器,如下所示:

探索 Airbyte 的增量数据同步_第4张图片

实例化 Postgres 目标连接器

定义一个名为增量目标的新 Postgres 目标,如下所示:

探索 Airbyte 的增量数据同步_第5张图片

探索增量追加同步

在本节中,您将探索使用增量同步 - 追加模式的增量数据库复制,并将检查用于规范化目标 Postgres 数据库中数据的 SQL。

定义第一个 Postgres 源表

现在,您将创建并填充一个名为 table_one 的表。首先使用以下命令在源 Postgres 数据库上打开一个 shell:

 
  
  1. docker exec -it airbyte-source psql --username=postgres

Postgres终端应该使用诸如postgres=#之类的提示进行响应。在源数据库中创建一个名为 table_one 的新表,如下所示:

 
  
  1. CREATE TABLE table_one(

  2. id integer PRIMARY KEY,

  3. name VARCHAR(200),

  4. updated_at timestamp DEFAULT NOW() NOT NULL

  5. );

请注意,该表包含一个名为 updated_at 的字段,该字段将用作游标字段(如上所述)。增量同步需要游标才能跟踪以前已同步的记录,以便它们不会重新发送到目标。

为了使游标正常工作,每次写入或修改记录时都必须更新此表中的updated_at字段。使用 Postgres 时,这可以通过 Postgres 触发器自动完成。通过将以下代码粘贴到源 Postgres 终端来创建一个名为 trigger_set_timestamp 的触发器:

 
  
  1. CREATE OR REPLACE FUNCTION trigger_set_timestamp()

  2. RETURNS TRIGGER AS '

  3. BEGIN

  4. NEW.updated_at = NOW();

  5. RETURN NEW;

  6. END;

  7. '

  8. LANGUAGE plpgsql;

触发器应在每次更新table_one表时执行,这是通过执行以下代码完成的:

 
  
  1. CREATE TRIGGER set_timestamp_on_table_one

  2. BEFORE UPDATE ON table_one

  3. FOR EACH ROW

  4. EXECUTE PROCEDURE trigger_set_timestamp();

现在用一些数据填充table_one并按如下方式查看:

 
  
  1. INSERT INTO table_one(id, name) VALUES(1, 'Eg1 IncApp');

  2. INSERT INTO table_one(id, name) VALUES(2, 'Eg2 IncApp');

  3. SELECT * FROM table_one;

table_one表应如下所示

 
  
  1. id | name | updated_at

  2. ----+------------+----------------------------

  3. 1 | Eg1 IncApp | 2022-09-01 11:01:41.666004

  4. 2 | Eg2 IncApp | 2022-09-01 11:01:41.68834

  5. (2 rows)

通过使用以下命令更新表中的一行,验证设置 updated_at 字段的触发器是否正确执行

 
  
  1. UPDATE table_one SET name='Eg2a IncAp' WHERE id=2;

  2. SELECT * FROM table_one;

table_one表应如下所示

 
  
  1. id | name | updated_at

  2. ----+------------+----------------------------

  3. 1 | Eg1 IncApp | 2022-09-01 11:01:41.666004

  4. 2 | Eg2a IncAp | 2022-09-01 11:02:05.017416

  5. (2 rows)

如果触发器已正确执行,则应看到 id=2 的记录的updated_at字段已修改,如上所示。

在源和目标之间创建连接

在本节中,您将创建一个连接,该连接将用于演示使用增量同步 |附加。 此新连接将使用您刚刚创建的连接器。

通过单击“连接”,然后单击“+ 新建连接”来创建新连接,如下所示(请注意,如果已实例化某些连接,则此按钮可能会出现在右上角):

探索 Airbyte 的增量数据同步_第6张图片

然后选择增量源,如下所示:

探索 Airbyte 的增量数据同步_第7张图片

选择增量目标,如下所示:

探索 Airbyte 的增量数据同步_第8张图片

您将看到如下所示的设置页面。将连接的名称设置为增量同步演示,并按如下所示进行配置:

探索 Airbyte 的增量数据同步_第9张图片

在上述配置中有几个区域进行了注释:

  1. 定义将标识此连接的名称 - 在本例中,我将其称为增量同步演示
  2. 为名为 table_one 的表选择增量追加复制模式。
  3. 选择“updated_at”作为table_one表的光标。

单击“设置连接”后将开始初始同步。完成后,您应该会在同步历史记录中看到以下状态:

记下作业 ID 和尝试 ID,在本例中分别为 149 和 0,如上面的屏幕截图中的日志路径 (/tmp/workspace/149/0/logs.log) 所示.log 您将需要这些值来查找用于第一个增量追加同步的 SQL 代码。

初始创建:概述

在第一次同步中,Airbyte 会将源表中的所有记录复制到目标数据库中的原始表中。然后,执行 dbt 生成的 SQL 命令,将原始数据规范化为最终目标表,如下所示:

探索 Airbyte 的增量数据同步_第10张图片

初始创建:查看 Postgres 目标

第一次同步完成后,您可以查看 Postgres 目标以查看复制数据的外观。执行以下命令以打开目标 Postgres 数据库的外壳:

 
  
  1. docker exec -it airbyte-destination psql --username=postgres

然后,您可以使用以下命令查看目标中表的名称:

 
  
  1. \dt;

这应该回应如下。

 
  
  1. List of relations

  2. Schema | Name | Type | Owner

  3. --------+------------------------+-------+----------

  4. public | _airbyte_raw_table_one | table | postgres

  5. public | table_one | table | postgres

  6. (2 rows)

初始创建:在目标中查看原始表

作为每个同步操作的第一步,Airbyte 将源数据库中table_one的记录复制到目标数据库中名为 _airbyte_raw_table_one 的原始表中。通过执行以下命令查看其内容:

 
  
  1. SELECT * FROM _airbyte_raw_table_one;

它应该响应一个如下所示的表:

 
  
  1. _airbyte_ab_id | _airbyte_data | _airbyte_emitted_at

  2. --------------------------------------+-----------------------------------------------------------------------------+----------------------------

  3. 2abc7493-bfc8-4493-ab62-de6ffe094a2d | {"id": 1, "name": "Eg1 IncApp", "updated_at": "2022-09-01T11:01:41.666004"} | 2022-09-01 11:12:03.301+00

  4. 06e67da7-9c6a-46b6-a2e5-e1d102e16c7e | {"id": 2, "name": "Eg2a IncAp", "updated_at": "2022-09-01T11:02:05.017416"} | 2022-09-01 11:12:03.301+00

  5. (2 rows)

除了包含源数据的字段之外,原始表中还有两个附加字段:

  • _airbyte_emitted_at告诉您 airbyte 将记录发送到目的地的时间。
  • _airbyte_ab_id是目标连接器在将每条记录发送到目标之前添加到每条记录的 UUID 值。这是一个 UUID(不是哈希),因此每次同步后,即使数据尚未修改,它也会针对每一行进行更改。

初始创建:查看目标中的规范化表

通过执行以下命令查看规范化表的内容:

 
  
  1. SELECT * FROM table_one;

规范化table_one表如下所示

 
  
  1. id | name | updated_at | _airbyte_ab_id | _airbyte_emitted_at | _airbyte_normalized_at | _airbyte_table_one_hashid

  2. ----+------------+----------------------------+--------------------------------------+----------------------------+-------------------------------+----------------------------------

  3. 1 | Eg1 IncApp | 2022-09-01 11:01:41.666004 | 2abc7493-bfc8-4493-ab62-de6ffe094a2d | 2022-09-01 11:12:03.301+00 | 2022-09-01 11:12:50.300405+00 | 43ed5ad798cc8204591c1254dabc9da8

  4. 2 | Eg2a IncAp | 2022-09-01 11:02:05.017416 | 06e67da7-9c6a-46b6-a2e5-e1d102e16c7e | 2022-09-01 11:12:03.301+00 | 2022-09-01 11:12:50.300405+00 | 2ec9ac8c405a07d980f9559637ec60df

  5. (2 rows)

除了从原始表中提取的列外,此规范化表还包括以下附加字段:

  • _airbyte_normalized_at告诉您记录何时规范化(即何时从原始数据创建记录)。
  • _airbyte_table_one_hashid是在规范化期间计算并添加的源字段的 md5 哈希。dbt 博客上这篇关于 md5 哈希的文章讨论了 md5 哈希的值。但是,请注意,因为源表中的updated_at字段包含在哈希计算中(正如我将在讨论 SQL 时看到的那样),并且每次修改给定记录时都会更新它,这与我在第一个教程中介绍的示例不同(仅使用 id 和名称计算哈希), 对于多个同步的给定记录,此哈希不一致。

初始创建:查看 SQL

为了理解上述列的创建过程,查看用于规范化数据的 SQL 代码会很有帮助。为此,您将需要您之前提取的感兴趣的同步操作中的作业 ID 尝试 ID

 airbyte-server docker 容器中创建一个 bash shell,如下所示:

 
  
  1. docker exec -it airbyte-server /bin/bash

现在,您将查看用于从具有增量追加模式的名为 _airbyte_raw_table_one 的表中创建名为 table_one 的表的 SQL。我使用之前记下的作业 ID 149 和尝试 ID 0 来查看带有 cat 命令的 SQL,如下所示:

 
  
  1. cat /tmp/workspace/149/0/build/run/airbyte_utils/models/generated/airbyte_incremental/public/table_one.sql

这将返回已用于将原始数据转换为规范化表的 SQL。用于创建增量追加表的 SQL 与上一教程中讨论的完整刷新追加 SQL 相同。但是,与完全刷新追加模式相反,只有已在源中插入或更新的数据才复制到原始目标表中 – 这由源连接器处理,该连接器仅选择源上的新记录以复制到目标,因此不会影响 SQL。

i️ 由于此首次同步会创建目标表,因此后续同步中使用的 SQL 的组织方式不同。本教程稍后将对此进行讨论。

我将这个SQL分解为四个主要部分,供下面讨论。SQL 的第一部分显示代码创建最终的table_one表,并从原始_airbyte_raw_table_one json 表中提取各种字段。

 
  
  1. create table "postgres".public."table_one"

  2. as (

  3. with __dbt__cte__table_one_ab1 as (

  4. -- SQL model to parse JSON blob stored in a single column and extract into separated field columns as described by the JSON Schema

  5. -- depends_on: "postgres".public._airbyte_raw_table_one

  6. select

  7. jsonb_extract_path_text(_airbyte_data, 'id') as "id",

  8. jsonb_extract_path_text(_airbyte_data, 'name') as "name",

  9. jsonb_extract_path_text(_airbyte_data, 'updated_at') as updated_at,

  10. _airbyte_ab_id,

  11. _airbyte_emitted_at,

  12. now() as _airbyte_normalized_at

  13. from "postgres".public._airbyte_raw_table_one as table_alias

  14. -- table_one

  15. where 1 = 1

  16. ),

SQL 的下一部分将每个字段强制转换为适当的类型,如下所示:

 
  
  1. __dbt__cte__table_one_ab2 as (

  2. -- SQL model to cast each column to its adequate SQL type converted from the JSON schema type

  3. -- depends_on: __dbt__cte__table_one_ab1

  4. select

  5. cast("id" as

  6. bigint

  7. ) as "id",

  8. cast("name" as text) as "name",

  9. cast(nullif(updated_at, '') as

  10. timestamp

  11. ) as updated_at,

  12. _airbyte_ab_id,

  13. _airbyte_emitted_at,

  14. now() as _airbyte_normalized_at

  15. from __dbt__cte__table_one_ab1

  16. -- table_one

  17. where 1 = 1

  18. ),

SQL 的下一部分将添加一个 md5 哈希。

 
  
  1. __dbt__cte__table_one_ab3 as (

  2. -- SQL model to build a hash column based on the values of this record

  3. -- depends_on: __dbt__cte__table_one_ab2

  4. select

  5. md5(cast(coalesce(cast("id" as text), '') || '-' || coalesce(cast("name" as text), '') || '-' || coalesce(cast(updated_at as text), '') as text)) as _airbyte_table_one_hashid,

  6. tmp.*

  7. from __dbt__cte__table_one_ab2 tmp

  8. -- table_one

  9. where 1 = 1

  10. )

最后,SQL 的最后一部分选择将写入目标table_one表中的字段。

 
  
  1. -- Final base SQL model

  2. -- depends_on: __dbt__cte__table_one_ab3

  3. select

  4. "id",

  5. "name",

  6. updated_at,

  7. _airbyte_ab_id,

  8. _airbyte_emitted_at,

  9. now() as _airbyte_normalized_at,

  10. _airbyte_table_one_hashid

  11. from __dbt__cte__table_one_ab3

  12. -- table_one from "postgres".public._airbyte_raw_table_one

  13. where 1 = 1

  14. );

更新:概述

下图显示了在源系统中修改记录,然后执行同步时发生的情况。在这种情况下,将从源复制记录的更新版本,并将其追加到原始表和目标中的最终表。

i️ 请注意,即使源仅包含两条记录,原始目标表和规范化目标表也分别包含三条记录。这是因为   id 为 2 的记录的当前版本和先前版本(上一次同步的版本,其中 updated_at=t1 和新版本,其中   updated_at=t2)将存储在每个目标表中。

探索 Airbyte 的增量数据同步_第11张图片

更新:修改源中的记录

返回到本教程前面打开的 airbyte-source 容器中的 Postgres shell,更新 table_one 中的记录并按如下所示查看表:

 
  
  1. UPDATE table_one SET name='Eg2b IncAp' WHERE id=2;

  2. SELECT * FROM table_one;

table_one表现在应如下所示:

 
  
  1. id | name | updated_at

  2. ----+------------+----------------------------

  3. 1 | Eg1 IncApp | 2022-09-01 11:01:41.666004

  4. 2 | Eg2b IncAp | 2022-09-01 11:16:38.093877

  5. (2 rows)

名称和updated_at值已按预期更新。通过单击连接 UI 中的“立即同步”来执行新的同步,然后等待同步完成。您应该会看到一个响应,指示已发出一条记录,如下所示:

i️ 请注意,与  上一教程中讨论的完全同步模式相反,在每次同步时都会发出源中的所有记录,而在增量同步模式下,仅发出新的或修改的记录 - 这在源连接器逻辑中处理,该逻辑仅选择源中的新文档以复制到目标。

已发出一条记录,该记录对应于刚刚更新的记录。此外,记下作业 ID 和尝试 ID,在本例中为 150 和 0。稍后将使用这些值来查看已用于规范化的 SQL。

更新:在目标中查看原始表

通过在目标 Postgres shell 中执行以下命令来查看名为 _airbyte_raw_table_one 的原始表:

 
  
  1. SELECT * FROM _airbyte_raw_table_one;

它应该响应一个如下所示的表:

 
  
  1. _airbyte_ab_id | _airbyte_data | _airbyte_emitted_at

  2. --------------------------------------+-----------------------------------------------------------------------------+----------------------------

  3. 2abc7493-bfc8-4493-ab62-de6ffe094a2d | {"id": 1, "name": "Eg1 IncApp", "updated_at": "2022-09-01T11:01:41.666004"} | 2022-09-01 11:12:03.301+00

  4. 06e67da7-9c6a-46b6-a2e5-e1d102e16c7e | {"id": 2, "name": "Eg2a IncAp", "updated_at": "2022-09-01T11:02:05.017416"} | 2022-09-01 11:12:03.301+00

  5. 4559d1dd-e5a6-4c86-a8b5-afa8c7f3f833 | {"id": 2, "name": "Eg2b IncAp", "updated_at": "2022-09-01T11:16:38.093877"} | 2022-09-01 11:17:11.63+00

  6. (3 rows)

更新:查看目标中的规范化表

通过执行以下命令查看规范化表的内容:

 
  
  1. SELECT * FROM table_one;

规范化table_one表如下所示:

 
  
  1. id | name | updated_at | _airbyte_ab_id | _airbyte_emitted_at | _airbyte_normalized_at | _airbyte_table_one_hashid

  2. ----+------------+----------------------------+--------------------------------------+----------------------------+-------------------------------+----------------------------------

  3. 1 | Eg1 IncApp | 2022-09-01 11:01:41.666004 | 2abc7493-bfc8-4493-ab62-de6ffe094a2d | 2022-09-01 11:12:03.301+00 | 2022-09-01 11:17:57.549949+00 | 43ed5ad798cc8204591c1254dabc9da8

  4. 2 | Eg2a IncAp | 2022-09-01 11:02:05.017416 | 06e67da7-9c6a-46b6-a2e5-e1d102e16c7e | 2022-09-01 11:12:03.301+00 | 2022-09-01 11:17:57.549949+00 | 2ec9ac8c405a07d980f9559637ec60df

  5. 2 | Eg2b IncAp | 2022-09-01 11:16:38.093877 | 4559d1dd-e5a6-4c86-a8b5-afa8c7f3f833 | 2022-09-01 11:17:11.63+00 | 2022-09-01 11:17:57.549949+00 | 40f631f32174002c94b689d73ecb2fee

  6. (3 rows)

请注意,有两个 id=2 的记录副本。使用增量追加同步模式时,这是预期的,因为每次插入或更新记录时,都会将该记录的新副本插入到目标中。

i️ 精明的读者可能会注意到,通过查看  _airbyte_normalized_at的值,似乎  整个表都已重新规范化 - 而不仅仅是已更新的记录。这是因为在最近一次同步中发送的记录以及  上一次同步中的记录将在每次  同步操作中规范化 - 下面给出的 SQL 分析将更详细地解释为什么会发生这种情况。

更新:查看 SQL

在本节中,您将查看在源上更新记录后用于增量追加规范化table_one的 SQL 代码。返回到您打开的 airbyte 服务器容器的终端,并使用您的作业 ID(在我的案例中为 150)和您的尝试 ID(在我的案例中为 0),使用以下命令查看 SQL:

 
  
  1. cat /tmp/workspace/150/0/build/run/airbyte_utils/models/generated/airbyte_incremental/public/table_one.sql

它使用以下 SQL 进行响应:

 
  
  1. delete from "postgres".public."table_one"

  2. where (_airbyte_ab_id) in (

  3. select (_airbyte_ab_id)

  4. from "table_one__dbt_tmp102442422971"

  5. );

  6. insert into "postgres".public."table_one" ("id", "name", "updated_at", "_airbyte_ab_id", "_airbyte_emitted_at", "_airbyte_normalized_at", "_airbyte_table_one_hashid")

  7. (

  8. select "id", "name", "updated_at", "_airbyte_ab_id", "_airbyte_emitted_at", "_airbyte_normalized_at", "_airbyte_table_one_hashid"

  9. from "table_one__dbt_tmp102442422971"

  10. )

第二次增量追加同步的此 SQL 代码与增量追加同步的第一次迭代中使用的 SQL 不同。

i️ 此 SQL 与  上一教程中讨论使用  完全刷新 | 追加同步模式完成的第二次同步时详细讨论的 SQL 代码基本相同。

在高级别上,此 SQL 代码将所有记录从名为 table_one__dbt_tmp102442422971 的临时表复制到 table_one 中。如果记录已存在于目标表中,并且该记录也出现在临时表中,则在将整个临时表插入目标表之前,可以通过将其从目标表中删除来避免重复。

在此同步和后续同步中,主逻辑在创建临时表期间应用。要查看用于创建它的 SQL,请查看 dbt 日志文件,该文件可以通过执行以下命令来查看:

 
  
  1. cat /tmp/workspace/150/0/logs/dbt.log

在日志中搜索临时表的创建,在本例中称为 table_one__dbt_tmp102442422971。用于创建临时表的 SQL 粘贴如下:

 
  
  1. create temporary table "table_one__dbt_tmp102442422971"

  2. as (

  3. with __dbt__cte__table_one_ab1 as (

  4. -- SQL model to parse JSON blob stored in a single column and extract into separated field columns as described by the JSON Schema

  5. -- depends_on: "postgres".public._airbyte_raw_table_one

  6. select

  7. jsonb_extract_path_text(_airbyte_data, 'id') as "id",

  8. jsonb_extract_path_text(_airbyte_data, 'name') as "name",

  9. jsonb_extract_path_text(_airbyte_data, 'updated_at') as updated_at,

  10. _airbyte_ab_id,

  11. _airbyte_emitted_at,

  12. now() as _airbyte_normalized_at

  13. from "postgres".public._airbyte_raw_table_one as table_alias

  14. -- table_one

  15. where 1 = 1

  16. ), __dbt__cte__table_one_ab2 as (

  17. -- SQL model to cast each column to its adequate SQL type converted from the JSON schema type

  18. -- depends_on: __dbt__cte__table_one_ab1

  19. select

  20. cast("id" as

  21. bigint

  22. ) as "id",

  23. cast("name" as text) as "name",

  24. cast(nullif(updated_at, '') as

  25. timestamp

  26. ) as updated_at,

  27. _airbyte_ab_id,

  28. _airbyte_emitted_at,

  29. now() as _airbyte_normalized_at

  30. from __dbt__cte__table_one_ab1

  31. -- table_one

  32. where 1 = 1

  33. ), __dbt__cte__table_one_ab3 as (

  34. -- SQL model to build a hash column based on the values of this record

  35. -- depends_on: __dbt__cte__table_one_ab2

  36. select

  37. md5(cast(coalesce(cast("id" as text), '') || '-' || coalesce(cast("name" as text), '') || '-' || coalesce(cast(updated_at as text), '') as text)) as _airbyte_table_one_hashid,

  38. tmp.*

  39. from __dbt__cte__table_one_ab2 tmp

  40. -- table_one

  41. where 1 = 1

  42. )-- Final base SQL model

  43. -- depends_on: __dbt__cte__table_one_ab3

  44. select

  45. "id",

  46. "name",

  47. updated_at,

  48. _airbyte_ab_id,

  49. _airbyte_emitted_at,

  50. now() as _airbyte_normalized_at,

  51. _airbyte_table_one_hashid

  52. from __dbt__cte__table_one_ab3

  53. -- table_one from "postgres".public._airbyte_raw_table_one

  54. where 1 = 1

  55. and coalesce(

  56. cast(_airbyte_emitted_at as

  57. timestamp with time zone

  58. ) >= (select max(cast(_airbyte_emitted_at as

  59. timestamp with time zone

  60. )) from "postgres".public."table_one"),

  61. true)

  62. );

此 SQL 与名为 table_one.sql 的文件中增量追加同步的第一次迭代中的 SQL 几乎相同,但在该示例中,名为 table_one 的目标表是在不使用临时表的情况下直接创建的。

前面的描述适用于此 SQL 的大部分内容。但是,此 SQL 的末尾还有一个额外的代码块,它减少了将处理的记录数,以仅包括在最近同步中发送的记录,以及上一次同步中的记录(如本期所述)。这是通过从目标表中提取最大的_airbyte_emitted_at值,并且仅从原始表中选择要_airbyte_emitted_at大于或等于此值的记录进行规范化来实现的。这会将选择进行规范化的记录数减少到仅在最近同步中发送的记录以及上一次同步中的记录

插入:概述

在此步骤中,您将在源表中插入 id 为 3 的新记录。此新记录将追加到目标中的原始表中,然后规范化并追加到最终数据表,如下所示:

探索 Airbyte 的增量数据同步_第12张图片

插入:在源中写入新记录

返回到本教程前面打开的 airbyte-source 容器中的 Postgres shell,并将新记录插入table_two并按如下所示查看它:

 
  
  1. INSERT INTO table_two(id, name) VALUES(3, 'Eg3 DD+Hst');

  2. SELECT * FROM table_two;

table_two表应如下所示:

 
  
  1. id | name | updated_at

  2. ----+------------+----------------------------

  3. 1 | Eg1 DD+Hst | 2022-09-01 16:18:07.569818

  4. 2 | Eg2b DD+Hs | 2022-09-01 17:02:14.841419

  5. 3 | Eg3 DD+Hst | 2022-09-01 17:05:19.570672

  6. (3 rows)

通过单击连接 UI 中的“立即同步”来执行新的同步,然后等待同步完成。

您应该看到已发出一条记录,该记录对应于您刚刚插入table_one中的记录。

插入:查看目标原始表

通过执行以下命令,查看增量追加同步到名为 _airbyte_raw_table_one 的原始表中的内容:

 
  
  1. SELECT * FROM _airbyte_raw_table_one;

它应该响应一个表,如下所示:

 
  
  1. _airbyte_ab_id | _airbyte_data | _airbyte_emitted_at

  2. --------------------------------------+-----------------------------------------------------------------------------+----------------------------

  3. 2abc7493-bfc8-4493-ab62-de6ffe094a2d | {"id": 1, "name": "Eg1 IncApp", "updated_at": "2022-09-01T11:01:41.666004"} | 2022-09-01 11:12:03.301+00

  4. 06e67da7-9c6a-46b6-a2e5-e1d102e16c7e | {"id": 2, "name": "Eg2a IncAp", "updated_at": "2022-09-01T11:02:05.017416"} | 2022-09-01 11:12:03.301+00

  5. 4559d1dd-e5a6-4c86-a8b5-afa8c7f3f833 | {"id": 2, "name": "Eg2b IncAp", "updated_at": "2022-09-01T11:16:38.093877"} | 2022-09-01 11:17:11.63+00

  6. 94871526-e631-49c6-a2f8-87a78755f8ae | {"id": 3, "name": "Eg3 IncApp", "updated_at": "2022-09-01T11:23:30.195854"} | 2022-09-01 11:24:19.629+00

  7. (4 rows)

插入:查看目标中的规范化表

通过执行以下命令查看规范化表的内容:

 
  
  1. SELECT * FROM table_one;

规范化table_one表如下所示:

 
  
  1. id | name | updated_at | _airbyte_ab_id | _airbyte_emitted_at | _airbyte_normalized_at | _airbyte_table_one_hashid

  2. ----+------------+----------------------------+--------------------------------------+----------------------------+-------------------------------+----------------------------------

  3. 1 | Eg1 IncApp | 2022-09-01 11:01:41.666004 | 2abc7493-bfc8-4493-ab62-de6ffe094a2d | 2022-09-01 11:12:03.301+00 | 2022-09-01 11:17:57.549949+00 | 43ed5ad798cc8204591c1254dabc9da8

  4. 2 | Eg2a IncAp | 2022-09-01 11:02:05.017416 | 06e67da7-9c6a-46b6-a2e5-e1d102e16c7e | 2022-09-01 11:12:03.301+00 | 2022-09-01 11:17:57.549949+00 | 2ec9ac8c405a07d980f9559637ec60df

  5. 2 | Eg2b IncAp | 2022-09-01 11:16:38.093877 | 4559d1dd-e5a6-4c86-a8b5-afa8c7f3f833 | 2022-09-01 11:17:11.63+00 | 2022-09-01 11:25:06.485075+00 | 40f631f32174002c94b689d73ecb2fee

  6. 3 | Eg3 IncApp | 2022-09-01 11:23:30.195854 | 94871526-e631-49c6-a2f8-87a78755f8ae | 2022-09-01 11:24:19.629+00 | 2022-09-01 11:25:06.485075+00 | e80c105c331899e3d7bcb8eb8e69bd10

  7. (4 rows)

已插入 id=3 的记录,之前的记录与之前相同。此外,如前所述,当前同步和先前同步的记录已规范化,通过查看_airbyte_normalized_at列可以看出。

插入:查看 SQL

在本节中,您将查看用于在将记录插入源后对table_one进行增量追加规范化的 SQL 代码。返回到已打开 airbyte 服务器容器的终端,并使用作业 ID 139 和尝试 ID 0,使用以下命令查看 SQL:

 
  
  1. cat /tmp/workspace/151/0/build/run/airbyte_utils/models/generated/airbyte_incremental/public/table_one.sql

它使用以下 SQL 进行响应:

 
  
  1. delete from "postgres".public."table_one"

  2. where (_airbyte_ab_id) in (

  3. select (_airbyte_ab_id)

  4. from "table_one__dbt_tmp112543672970"

  5. );

  6. insert into "postgres".public."table_one" ("id", "name", "updated_at", "_airbyte_ab_id", "_airbyte_emitted_at", "_airbyte_normalized_at", "_airbyte_table_one_hashid")

  7. (

  8. select "id", "name", "updated_at", "_airbyte_ab_id", "_airbyte_emitted_at", "_airbyte_normalized_at", "_airbyte_table_one_hashid"

  9. from "table_one__dbt_tmp112543672970"

  10. )

这与上次同步中演示的 SQL 相同。您还可以通过查看 dbt 日志来找到用于创建临时表的 SQL,如下所示:

 
  
  1. cat /tmp/workspace/151/0/logs/dbt.log

此 SQL 的逻辑与上一节中讨论的 SQL 相同,因此不需要其他讨论。

删除:概述

接下来,您将从源表中删除 id 为 3 的记录 - 但是,如前所述,增量同步复制模式不会传播删除操作。下图表示删除源上的 id=3 的记录,这对目标没有影响:

探索 Airbyte 的增量数据同步_第13张图片

删除:从源中删除记录

返回到本教程前面打开的 airbyte-source 容器中的 Postgres shell,从table_one中删除记录并按如下所示查看它:

 
  
  1. DELETE FROM table_one where id=3;

  2. SELECT * FROM table_one;

table_one表应如下所示:

 
  
  1. id | name | updated_at

  2. ----+------------+----------------------------

  3. 1 | Eg1 IncApp | 2022-09-01 11:01:41.666004

  4. 2 | Eg2b IncAp | 2022-09-01 11:16:38.093877

  5. (2 rows)

您应该看到 id 为 3 的新记录已从源表中删除。通过单击连接 UI 中的“立即同步”来执行新的同步,然后等待同步完成。

请注意,已发出零条记录,换句话说,尚未将任何更改从源传播到目标。这可能会让人感到意外,但这是增量复制的限制。如增量追加概述文档中所述,仓库目标中的记录永远不会被删除或更改。这就是为什么在某些情况下可能首选更改数据捕获 (CDC) 同步的原因之一。或者,可以考虑软删除。

删除:查看目标中的原始表

通过执行以下命令,查看增量追加同步到名为 _airbyte_raw_table_one 的原始表中的内容:

 
  
  1. SELECT * FROM _airbyte_raw_table_one;

它应该响应一个表,如下所示:

 
  
  1. _airbyte_ab_id | _airbyte_data | _airbyte_emitted_at

  2. --------------------------------------+-----------------------------------------------------------------------------+----------------------------

  3. 2abc7493-bfc8-4493-ab62-de6ffe094a2d | {"id": 1, "name": "Eg1 IncApp", "updated_at": "2022-09-01T11:01:41.666004"} | 2022-09-01 11:12:03.301+00

  4. 06e67da7-9c6a-46b6-a2e5-e1d102e16c7e | {"id": 2, "name": "Eg2a IncAp", "updated_at": "2022-09-01T11:02:05.017416"} | 2022-09-01 11:12:03.301+00

  5. 4559d1dd-e5a6-4c86-a8b5-afa8c7f3f833 | {"id": 2, "name": "Eg2b IncAp", "updated_at": "2022-09-01T11:16:38.093877"} | 2022-09-01 11:17:11.63+00

  6. 94871526-e631-49c6-a2f8-87a78755f8ae | {"id": 3, "name": "Eg3 IncApp", "updated_at": "2022-09-01T11:23:30.195854"} | 2022-09-01 11:24:19.629+00

  7. (4 rows)

表与在源数据库上删除记录之前显示的表完全相同。换句话说,如上所述,删除操作没有也不会传播到目标。

i️ 无法直接传播已删除的记录是增量同步的主要缺点之一。这是因为源系统上的查询选择了复制到目标的记录,以查找自上次同步以来已插入或修改的记录。此类查询不会返回已删除的任何记录,因此删除的记录不会传播到目标。解决此缺点的两种常见方法是   CDC 复制或使用  软删除。

删除:查看目标中的规范化表

通过执行以下命令查看规范化表的内容:

 
  
  1. SELECT * FROM table_one;

规范化table_one表如下所示:

 
  
  1. id | name | updated_at | _airbyte_ab_id | _airbyte_emitted_at | _airbyte_normalized_at | _airbyte_table_one_hashid

  2. ----+------------+----------------------------+--------------------------------------+----------------------------+-------------------------------+----------------------------------

  3. 1 | Eg1 IncApp | 2022-09-01 11:01:41.666004 | 2abc7493-bfc8-4493-ab62-de6ffe094a2d | 2022-09-01 11:12:03.301+00 | 2022-09-01 11:17:57.549949+00 | 43ed5ad798cc8204591c1254dabc9da8

  4. 2 | Eg2a IncAp | 2022-09-01 11:02:05.017416 | 06e67da7-9c6a-46b6-a2e5-e1d102e16c7e | 2022-09-01 11:12:03.301+00 | 2022-09-01 11:17:57.549949+00 | 2ec9ac8c405a07d980f9559637ec60df

  5. 2 | Eg2b IncAp | 2022-09-01 11:16:38.093877 | 4559d1dd-e5a6-4c86-a8b5-afa8c7f3f833 | 2022-09-01 11:17:11.63+00 | 2022-09-01 11:25:06.485075+00 | 40f631f32174002c94b689d73ecb2fee

  6. 3 | Eg3 IncApp | 2022-09-01 11:23:30.195854 | 94871526-e631-49c6-a2f8-87a78755f8ae | 2022-09-01 11:24:19.629+00 | 2022-09-01 11:29:30.12971+00 | e80c105c331899e3d7bcb8eb8e69bd10

  7. (4 rows)

请注意,目标table_one中的最新条目已重新规范化 - 如前所述,这是因为 Airbyte 执行的 SQL 将重新规范化目标表中_airbyte_emitted_at具有上一个最新值的所有记录,如本期所述。

删除:查看 SQL

此同步和所有后续同步操作中使用的 SQL 实现的逻辑与初始同步后用于所有先前同步的 SQL 的逻辑相同。因此,我不再进一步讨论这个问题。

无需任何修改即可同步:概述

如果在不对源数据库进行任何修改的情况下执行同步,则不会发出任何记录,也不会对目标数据进行任何更改*。因此,在不修改源数据的情况下执行同步后,数据表的外观将与同步操作之前相同,如下所示。

i️ * 此语句有一个小例外,因为最终表中某些记录的规范化时间将被修改,此图中未对此进行演示。

探索 Airbyte 的增量数据同步_第14张图片

同步无需任何修改

您可以通过单击“立即同步”,然后验证是否未发出任何记录来确认这一点,如下所示。

‍‍

无需任何修改即可同步:查看目标中的原始表

执行以下命令查看原始表。

 
  
  1. SELECT * FROM _airbyte_raw_table_one;

它应该响应一个表,如下所示:

 
  
  1. _airbyte_ab_id | _airbyte_data | _airbyte_emitted_at

  2. --------------------------------------+-----------------------------------------------------------------------------+----------------------------

  3. 2abc7493-bfc8-4493-ab62-de6ffe094a2d | {"id": 1, "name": "Eg1 IncApp", "updated_at": "2022-09-01T11:01:41.666004"} | 2022-09-01 11:12:03.301+00

  4. 06e67da7-9c6a-46b6-a2e5-e1d102e16c7e | {"id": 2, "name": "Eg2a IncAp", "updated_at": "2022-09-01T11:02:05.017416"} | 2022-09-01 11:12:03.301+00

  5. 4559d1dd-e5a6-4c86-a8b5-afa8c7f3f833 | {"id": 2, "name": "Eg2b IncAp", "updated_at": "2022-09-01T11:16:38.093877"} | 2022-09-01 11:17:11.63+00

  6. 94871526-e631-49c6-a2f8-87a78755f8ae | {"id": 3, "name": "Eg3 IncApp", "updated_at": "2022-09-01T11:23:30.195854"} | 2022-09-01 11:24:19.629+00

  7. (4 rows)

正如预期的那样,这与同步之前目标中的原始表相同。

同步而不进行任何修改:查看目标中的规范化表

通过执行以下命令查看规范化表的内容:

 
  
  1. SELECT * FROM table_one;

规范化table_one表如下所示:

 
  
  1. id | name | updated_at | _airbyte_ab_id | _airbyte_emitted_at | _airbyte_normalized_at | _airbyte_table_one_hashid

  2. ----+------------+----------------------------+--------------------------------------+----------------------------+-------------------------------+----------------------------------

  3. 1 | Eg1 IncApp | 2022-09-01 11:01:41.666004 | 2abc7493-bfc8-4493-ab62-de6ffe094a2d | 2022-09-01 11:12:03.301+00 | 2022-09-01 11:17:57.549949+00 | 43ed5ad798cc8204591c1254dabc9da8

  4. 2 | Eg2a IncAp | 2022-09-01 11:02:05.017416 | 06e67da7-9c6a-46b6-a2e5-e1d102e16c7e | 2022-09-01 11:12:03.301+00 | 2022-09-01 11:17:57.549949+00 | 2ec9ac8c405a07d980f9559637ec60df

  5. 2 | Eg2b IncAp | 2022-09-01 11:16:38.093877 | 4559d1dd-e5a6-4c86-a8b5-afa8c7f3f833 | 2022-09-01 11:17:11.63+00 | 2022-09-01 11:25:06.485075+00 | 40f631f32174002c94b689d73ecb2fee

  6. 3 | Eg3 IncApp | 2022-09-01 11:23:30.195854 | 94871526-e631-49c6-a2f8-87a78755f8ae | 2022-09-01 11:24:19.629+00 | 2022-09-01 11:37:07.613905+00 | e80c105c331899e3d7bcb8eb8e69bd10

  7. (4 rows)

查看 _airbyte_normalized_at 的值,您可以看到最后一个条目已重新规范化,即使它尚未被修改。如前所述,这是因为每次同步都会对目标中的最新记录进行规范化。

探索增量重复数据删除 + 历史记录同步

在本节中,您将探索使用增量同步 |重复数据删除同步模式,并将检查用于规范化目标 Postgres 数据库中的原始数据的 SQL。

增量重复数据删除 + 历史记录同步的高级概述

在这种同步模式下,Airbyte 首先将源数据复制到目标中的原始数据表中,然后通过在目标中执行 SQL 语句来创建两个规范化表,如下图所示:

探索 Airbyte 的增量数据同步_第15张图片

定义第二个 Postgres 源表

在本教程的这一部分中,您将登录到源 Postgres 数据库,并创建并填充一个新表,该表将用作演示增量复制的源。返回到您之前打开的 airbyte-source 中的 Postgres shell,并在源数据库中创建一个名为 table_two 的新表,如下所示:

 
  
  1. CREATE TABLE table_two(

  2. id integer PRIMARY KEY,

  3. name VARCHAR(200),

  4. updated_at timestamp DEFAULT NOW() NOT NULL

  5. );

接下来,定义应在每次更新table_two表时执行的触发器,这是通过执行以下代码完成的。这并不是说这是指本教程前面定义的名为trigger_set_timestamp的过程:

 
  
  1. CREATE TRIGGER set_timestamp_on_table_two

  2. BEFORE UPDATE ON table_two

  3. FOR EACH ROW

  4. EXECUTE PROCEDURE trigger_set_timestamp();

用一些数据填充第二个表,并按如下方式查看:

 
  
  1. INSERT INTO table_two(id, name) VALUES(1, 'Eg1 DD+Hst');

  2. INSERT INTO table_two(id, name) VALUES(2, 'Eg2 DD+Hst');

  3. SELECT * FROM table_two;

table_two表如下所示

 
  
  1. id | name | updated_at

  2. ----+------------+----------------------------

  3. 1 | Eg1 DD+Hst | 2022-09-01 16:18:07.569818

  4. 2 | Eg2 DD+Hst | 2022-09-01 16:18:07.581552

  5. (2 rows)

通过更新表中的一行并使用以下命令查看表,验证设置 updated_at 字段的触发器是否正确执行:

 
  
  1. UPDATE table_two SET name='Eg2a DD+Hs' WHERE id=2;

  2. SELECT * FROM table_two;

table_two表如下所示

 
  
  1. id | name | updated_at

  2. ----+------------+----------------------------

  3. 1 | Eg1 DD+Hst | 2022-09-01 16:18:07.569818

  4. 2 | Eg2a DD+Hs | 2022-09-01 16:30:13.939030

  5. (2 rows)

如果您的触发器已正确执行,那么您应该看到 id=2 的记录的updated_at字段已被修改table_two

检测新表并配置重复数据删除 + 历史记录复制

现在,您将配置 Airbyte 以检测刚刚创建的新表。为此,请单击之前定义的增量同步演示连接下的“复制”,然后单击刷新源架构”按钮,如下图所示。

探索 Airbyte 的增量数据同步_第16张图片

‍刷新架构后,您将能够选择要复制table_two

探索 Airbyte 的增量数据同步_第17张图片

使用以下设置配置上图中批注的流:

  1. (可选)禁用table_one同步,因为它与本节无关。
  2. 启用table_two同步。
  3. 选择增量 |重复数据删除 + 历史记录作为table_two表的复制模式。
  4. 选择“updated_at”作为table_two表的光标。
  5. 选择 id 字段作为主键,该主键将在目标中table_two重复数据删除表的重复数据删除中使用。

然后点击右下角的保存更改按钮。此时,您可能会看到以下弹出窗口,并可以单击“保存连接”。

探索 Airbyte 的增量数据同步_第18张图片

在右下角,您将看到以下旋转图标,而不是“保存连接”按钮。它最终应该返回到以下内容,此时您的连接应该已准备就绪。

返回到连接页面,您应该在其中看到同步已成功,如下所示:

请注意,发出了 2 条记录,对应于已写入table_two的两条记录。

初始创建:概述

在第一次同步中,Airbyte 会将源表中的所有记录复制到目标数据库中的原始表中。然后,执行 dbt 生成的 SQL 命令,将原始数据规范化为历史记录表。在此历史记录表上执行其他 SQL 命令以创建最终的重复数据删除表,如下所示:

初始创建:查看 Postgres 目标

返回到之前打开的目标 Postgres shell,然后可以使用以下命令查看目标中表的名称:

 
  
  1. \dt;

在我的配置中,它响应以下表列表。

 
  
  1. List of relations

  2. Schema | Name | Type | Owner

  3. --------+------------------------+-------+----------

  4. public | _airbyte_raw_table_one | table | postgres

  5. public | _airbyte_raw_table_two | table | postgres

  6. public | table_one | table | postgres

  7. public | table_two | table | postgres

  8. public | table_two_scd | table | postgres

  9. (5 rows)

请注意,除了名为 _airbyte_raw_table_two 的新原始表之外,还有两个新的规范化表。table_two_scd是历史表(其中 scd 表示缓慢变化的维度),table_two是重复的表。

初始创建:在目标中查看原始表

在创建源和目标之间的连接期间,使用增量重复数据删除 + 历史记录同步模式对table_two执行初始同步。数据被写入名为 _airbyte_raw_table_two 的原始表中,可以通过执行以下操作来查看该表:

 
  
  1. SELECT * FROM _airbyte_raw_table_two;

这应该使用如下所示的表进行响应:

 
  
  1. _airbyte_ab_id | _airbyte_data | _airbyte_emitted_at

  2. --------------------------------------+-----------------------------------------------------------------------------+----------------------------

  3. 3bd474b8-0329-4bce-bde7-aee7c5d30cc8 | {"id": 1, "name": "Eg1 DD+Hst", "updated_at": "2022-09-01T16:18:07.569818"} | 2022-09-01 16:52:44.103+00

  4. 4282344a-62c3-4634-a91a-e6dafb9b253a | {"id": 2, "name": "Eg2a DD+Hs", "updated_at": "2022-09-01T16:30:13.939030"} | 2022-09-01 16:52:44.103+00

  5. (2 rows)

除了包含源数据的字段之外,原始表中还有两个附加字段,即本教程前面介绍的_airbyte_emitted_at_airbyte_ab_id

初始创建:查看目标中的规范化表

规范化 SQL 从原始数据创建两个表,一个历史记录表 (table_two_scd) 和一个重复数据删除表 (table_two)。通过执行以下命令查看名为 table_two_scd 的历史记录表:

 
  
  1. SELECT * FROM table_two_scd;

这看起来如下。

 
  
  1. _airbyte_unique_key | _airbyte_unique_key_scd | id | name | updated_at | _airbyte_start_at | _airbyte_end_at | _airbyte_active_row | _airbyte_ab_id | _airbyte_emitted_at | _airbyte_normalized_at | _airbyte_table_two_hashid

  2. ----------------------------------+----------------------------------+----+------------+----------------------------+----------------------------+-----------------+---------------------+--------------------------------------+----------------------------+-------------------------------+----------------------------------

  3. c4ca4238a0b923820dcc509a6f75849b | 96a17eccedd409b3b3de3b411d431ab8 | 1 | Eg1 DD+Hst | 2022-09-01 16:18:07.569818 | 2022-09-01 16:18:07.569818 | | 1 | 3bd474b8-0329-4bce-bde7-aee7c5d30cc8 | 2022-09-01 16:52:44.103+00 | 2022-09-01 16:53:41.035633+00 | 78812b56ae516cb4bb4278c595c3b20e

  4. c81e728d9d4c2f636f067f89cc14862c | 064c6bc6ac9c9956a7188495284d8c07 | 2 | Eg2a DD+Hs | 2022-09-01 16:30:13.93903 | 2022-09-01 16:30:13.93903 | | 1 | 4282344a-62c3-4634-a91a-e6dafb9b253a | 2022-09-01 16:52:44.103+00 | 2022-09-01 16:53:41.035633+00 | d89c24a3d20ae9663d6f9a40f023149c

  5. (2 rows)

此表与其他表完全不同。除了前面讨论的规范化表中显示的列外,它还包括以下新列:

  • _airbyte_unique_key是主键字段(本示例中的 id 字段)的哈希,具有一些额外的逻辑来处理未定义的记录。
  • _airbyte_unique_key_scd是多个字段的哈希,可确保历史记录 (SCD) 表中出现的每一行都具有唯一值。
  • _airbyte_start_at指定给定版本的记录何时开始在源表中有效。这是根据源表中出现的该记录的新版本确定的,该版本通过其updated_at字段(或指定为游标的任何字段)的更改来检测。插入或更新后,将在历史表中创建一个新条目,_airbyte_start_at设置为updated_at时间。
  • _airbyte_end_at指定历史记录的给定版本何时在源表中停止有效。这是基于源表中 updated_at(或指定为游标的任何字段)值的更改,这表示源系统中的记录已更新,因此该记录的先前历史条目不再准确反映其当前状态。
  • _airbyte_active_row用于指定哪些行应包含在重复数据删除的表中(在本例中table_two)。

通过执行以下操作,查看目标中名为 table_two 的已消除重复数据表:

 
  
  1. SELECT * FROM table_two;

其外观如下:

 
  
  1. _airbyte_unique_key | id | name | updated_at | _airbyte_ab_id | _airbyte_emitted_at | _airbyte_normalized_at | _airbyte_table_two_hashid

  2. ----------------------------------+----+------------+----------------------------+--------------------------------------+----------------------------+-------------------------------+----------------------------------

  3. c4ca4238a0b923820dcc509a6f75849b | 1 | Eg1 DD+Hst | 2022-09-01 16:18:07.569818 | 3bd474b8-0329-4bce-bde7-aee7c5d30cc8 | 2022-09-01 16:52:44.103+00 | 2022-09-01 16:53:41.627757+00 | 78812b56ae516cb4bb4278c595c3b20e

  4. c81e728d9d4c2f636f067f89cc14862c | 2 | Eg2a DD+Hs | 2022-09-01 16:30:13.93903 | 4282344a-62c3-4634-a91a-e6dafb9b253a | 2022-09-01 16:52:44.103+00 | 2022-09-01 16:53:41.627757+00 | d89c24a3d20ae9663d6f9a40f023149c

  5. (2 rows)

虽然根据到目前为止已同步的少量条目可能还不清楚,但此表包含与源数据库中每条记录对应的单个记录。换句话说,历史表中显示的数据已删除重复数据,并且此表中仅显示给定记录的最新版本。这是通过SQL实现的,SQL只选择_airbyte_active_row为真的记录,并在SQL的讨论中进行了更详细的讨论。

初始创建:查看 SQL

在本节中,您将了解在使用增量重复数据删除历史记录时,第一次同步中使用的 SQL 代码,用于将原始数据规范化到目标表中。如您所见,此模式创建两个规范化表:

  1. 历史记录表,在此示例中称为 table_two_scd。此表包含每次同步时源表中的记录历史记录。每条记录的寿命通过在每行中使用_airbyte_start_at_airbyte_end_at来表示。
  2. 一个重复的表,在此示例中称为 table_two。此表中的数据对于每个主键都是唯一的。请注意,此表是通过运行 SQL 命令创建的,这些命令从名为 table_two_scd 的历史记录表中提取记录。

本节将指导您完成用于创建上述表的 SQL。这是一个多阶段的过程,涉及创建临时表 (table_two_stg),它是历史记录表 (table_two_scd) 的基础,而历史记录表又构成了重复数据删除表 (table_two) 的基础。

i️ 请注意,下面介绍的 cat 命令基于  作业 ID   170 和  尝试 ID 0,这是我在最近成功同步后从 Airbyte UI 中提取的。如果要继续操作,请务必将其替换为基于您自己的同步运行的值。

SQL 数据处理步骤概述

用于创建最终(重复数据删除)表和历史记录 (SCD) 表的 SQL 具有几个中间步骤,这些步骤使用公用表表达式(或 CTE)和临时表,如下图所示:

临时表 SQL - 创建table_two_stg

名为 table_two_stg 的临时表用作创建名为 table_two_scd 的历史记录表的基础。临时表是通过从原始表中读取记录来创建的,在此示例中称为 _airbyte_raw_table_two

通过在 airbyte 服务器容器中执行以下命令来查看创建临时表的 SQL:

 
  
  1. cat /tmp/workspace/170/0/build/run/airbyte_utils/models/generated/airbyte_incremental/public/table_two_stg.sql

SQL 的第一部分创建目标表,并从原始表 (_airbyte_raw_table_two) 中的嵌入式 JSON blob 中提取字段,并选择新的 Airbyte 创建的列,如下所示:

 
  
  1. create table "postgres"._airbyte_public."table_two_stg"

  2. as (

  3. with __dbt__cte__table_two_ab1 as (

  4. -- SQL model to parse JSON blob stored in a single column and extract into separated field columns as described by the JSON Schema

  5. -- depends_on: "postgres".public._airbyte_raw_table_two

  6. select

  7. jsonb_extract_path_text(_airbyte_data, 'id') as "id",

  8. jsonb_extract_path_text(_airbyte_data, 'name') as "name",

  9. jsonb_extract_path_text(_airbyte_data, 'updated_at') as updated_at,

  10. _airbyte_ab_id,

  11. _airbyte_emitted_at,

  12. now() as _airbyte_normalized_at

  13. from "postgres".public._airbyte_raw_table_two as table_alias

  14. -- table_two

  15. where 1 = 1

  16. ),

SQL 的下一部分负责将从嵌入式 JSON blob 中提取的每个字段强制转换为正确的类型。

 
  
  1. __dbt__cte__table_two_ab2 as (

  2. -- SQL model to cast each column to its adequate SQL type converted from the JSON schema type

  3. -- depends_on: __dbt__cte__table_two_ab1

  4. select

  5. cast("id" as

  6. bigint

  7. ) as "id",

  8. cast("name" as text) as "name",

  9. cast(nullif(updated_at, '') as

  10. timestamp

  11. ) as updated_at,

  12. _airbyte_ab_id,

  13. _airbyte_emitted_at,

  14. now() as _airbyte_normalized_at

  15. from __dbt__cte__table_two_ab1

  16. -- table_two

  17. where 1 = 1

  18. )

SQL 的下一部分创建存储在 _airbyte_table_two_hashid 中的 md5 哈希,并输出在 SQL 的上一节中创建的所有字段。

 
  
  1. -- SQL model to build a hash column based on the values of this record

  2. -- depends_on: __dbt__cte__table_two_ab2

  3. select

  4. md5(cast(coalesce(cast("id" as text), '') || '-' || coalesce(cast("name" as text), '') || '-' || coalesce(cast(updated_at as text), '') as text)) as _airbyte_table_two_hashid,

  5. tmp.*

  6. from __dbt__cte__table_two_ab2 tmp

  7. -- table_two

  8. where 1 = 1

  9. );

历史表 SQL – 创建table_two_scd

本节讨论用于创建名为 table_two_scd 的历史目标表的 SQL。创建此表的 SQL 使用刚刚讨论的临时表作为其输入。通过执行以下命令查看用于创建此新表的 SQL:

 
  
  1. cat /tmp/workspace/170/0/build/run/airbyte_utils/models/generated/airbyte_incremental/scd/public/table_two_scd.sql

此命令返回的 SQL 的第一部分定义创建的目标称为 table_two_scdtable_two_stg是输入。

 
  
  1. create table "postgres".public."table_two_scd"

  2. as (

  3. -- depends_on: ref('table_two_stg')

  4. with

  5. input_data as (

  6. select *

  7. from "postgres"._airbyte_public."table_two_stg"

  8. -- table_two from "postgres".public._airbyte_raw_table_two

  9. ),

SQL 的下一部分显示了前面讨论的以下值的计算:_airbyte_unique_key_airbyte_start_at_airbyte_end_at 和_airbyte_active_row

 
  
  1. scd_data as (

  2. -- SQL model to build a Type 2 Slowly Changing Dimension (SCD) table for each record identified by their primary key

  3. select

  4. md5(cast(coalesce(cast("id" as text), '') as text)) as _airbyte_unique_key,

  5. "id",

  6. "name",

  7. updated_at,

  8. updated_at as _airbyte_start_at,

  9. lag(updated_at) over (

  10. partition by cast("id" as text)

  11. order by

  12. updated_at is null asc,

  13. updated_at desc,

  14. _airbyte_emitted_at desc

  15. ) as _airbyte_end_at,

  16. case when row_number() over (

  17. partition by cast("id" as text)

  18. order by

  19. updated_at is null asc,

  20. updated_at desc,

  21. _airbyte_emitted_at desc

  22. ) = 1 then 1 else 0 end as _airbyte_active_row,

  23. _airbyte_ab_id,

  24. _airbyte_emitted_at,

  25. _airbyte_table_two_hashid

  26. from input_data

  27. ),

下一节显示以下_airbyte_unique_key_scd_airbyte_row_num的计算。

 
  
  1. dedup_data as (

  2. select

  3. -- we need to ensure de-duplicated rows for merge/update queries

  4. -- additionally, we generate a unique key for the scd table

  5. row_number() over (

  6. partition by

  7. _airbyte_unique_key,

  8. _airbyte_start_at,

  9. _airbyte_emitted_at

  10. order by _airbyte_active_row desc, _airbyte_ab_id

  11. ) as _airbyte_row_num,

  12. md5(cast(coalesce(cast(_airbyte_unique_key as text), '') || '-' || coalesce(cast(_airbyte_start_at as text), '') || '-' || coalesce(cast(_airbyte_emitted_at as text), '') as text)) as _airbyte_unique_key_scd,

  13. scd_data.*

  14. from scd_data

  15. )

最后,SQL 代码的以下部分通过从上述代码块中计算的dedup_data CTE 中仅选择一行,确保重复的历史记录(即具有相同_airbyte_unique_key_airbyte_start_at_airbyte_emitted_at值的记录)仅插入一次table_two_scd

 
  
  1. select

  2. _airbyte_unique_key,

  3. _airbyte_unique_key_scd,

  4. "id",

  5. "name",

  6. updated_at,

  7. _airbyte_start_at,

  8. _airbyte_end_at,

  9. _airbyte_active_row,

  10. _airbyte_ab_id,

  11. _airbyte_emitted_at,

  12. now() as _airbyte_normalized_at,

  13. _airbyte_table_two_hashid

  14. from dedup_data where _airbyte_row_num = 1

  15. );

重复表SQL - 创建table_two

本节讨论创建重复数据删除表的 SQL 代码,在本教程中,该表在目标中称为table_two(与在源中调用的名称相同)。如果记录在源表中仅出现一次,则它应仅在此删除重复数据的目标表中出现一次。

i️ 此表由 SQL 命令填充,这些命令使用  table_two_scd历史记录表作为输入数据。   

通过执行以下命令(替换作业 ID 和尝试 ID 以反映最近的同步),可以看到用于在目标 Postgres 数据库中创建table_two的 SQL:

 
  
  1. cat /tmp/workspace/170/0/build/run/airbyte_utils/models/generated/airbyte_incremental/public/table_two.sql

它使用以下 SQL 代码进行响应:

 
  
  1. create table "postgres".public."table_two"

  2. as (

  3. -- Final base SQL model

  4. -- depends_on: "postgres".public."table_two_scd"

  5. select

  6. _airbyte_unique_key,

  7. "id",

  8. "name",

  9. updated_at,

  10. _airbyte_ab_id,

  11. _airbyte_emitted_at,

  12. now() as _airbyte_normalized_at,

  13. _airbyte_table_two_hashid

  14. from "postgres".public."table_two_scd"

  15. -- table_two from "postgres".public._airbyte_raw_table_two

  16. where 1 = 1

  17. and _airbyte_active_row = 1

  18. );

这段代码非常简单,因为它所做的只是将 _airbyte_active_row = 1 的行从称为 table_two_scd 的历史记录表中复制到名为 table_two 的重复数据删除表。

i️ 如果历史记录表 (  table_two_scd) 中有多个记录的历史副本,则只有最近同步中的记录的  _airbyte_active_row值为 1。因此,通过仅复制名为   table_two_scd 的历史记录表中当前活动的行,将删除复制到  table_two中的数据。

更新:概述

下图显示,当您修改源系统中的记录,然后执行同步时,该更新的记录将复制到目标数据库中的原始表中,然后追加到历史记录表中。换句话说,即使源仅包含两条记录,原始和历史 (SCD) 目标表也分别包含三条记录 – 这是因为 id=2 的记录的当前版本和以前版本存储在每个目标表中。

但是,在此同步模式下,最终数据表被重复数据删除,并且仅包含与源系统中的每个唯一 ID 对应的每条记录的单个副本。

更新:修改源中的记录

返回到本教程前面打开的 airbyte 源容器中的 Postgres shell,更新 table_two 中的记录并按如下所示查看表:

 
  
  1. UPDATE table_two SET name='Eg2b DD+Hs' WHERE id=2;

  2. SELECT * FROM table_two;

table_two表现在应如下所示:

 
  
  1. id | name | updated_at

  2. ----+------------+----------------------------

  3. 1 | Eg1 DD+Hst | 2022-09-01 16:18:07.569818

  4. 2 | Eg2b DD+Hs | 2022-09-01 17:02:14.841419

  5. (2 rows)

名称和updated_at值已按预期更新。通过单击连接 UI 中的“立即同步”来执行新的同步,然后等待同步完成。您应该会看到一个响应,指示已发出一条记录,如下所示:

更新:在目标中查看原始表

在目标 Postgres 数据库上使用以下命令查看名为 _airbyte_raw_table_two 的增量重复数据删除历史记录原始表。

 
  
  1. SELECT * FROM _airbyte_raw_table_two;

它应该响应一个如下所示的表:

 
  
  1. _airbyte_ab_id | _airbyte_data | _airbyte_emitted_at

  2. --------------------------------------+-----------------------------------------------------------------------------+----------------------------

  3. 3bd474b8-0329-4bce-bde7-aee7c5d30cc8 | {"id": 1, "name": "Eg1 DD+Hst", "updated_at": "2022-09-01T16:18:07.569818"} | 2022-09-01 16:52:44.103+00

  4. 4282344a-62c3-4634-a91a-e6dafb9b253a | {"id": 2, "name": "Eg2a DD+Hs", "updated_at": "2022-09-01T16:30:13.939030"} | 2022-09-01 16:52:44.103+00

  5. 89377204-7801-49c8-a779-91da45a86cc3 | {"id": 2, "name": "Eg2b DD+Hs", "updated_at": "2022-09-01T17:02:14.841419"} | 2022-09-01 17:02:39.894+00

  6. (3 rows)

更新:查看目标中的规范化表

通过执行以下命令查看名为 table_two_scd 的历史记录表:

 
  
  1. SELECT * FROM table_two_scd;

如下所示。

 
  
  1. _airbyte_unique_key | _airbyte_unique_key_scd | id | name | updated_at | _airbyte_start_at | _airbyte_end_at | _airbyte_active_row | _airbyte_ab_id | _airbyte_emitted_at | _airbyte_normalized_at | _airbyte_table_two_hashid

  2. ----------------------------------+----------------------------------+----+------------+----------------------------+----------------------------+----------------------------+---------------------+--------------------------------------+----------------------------+-------------------------------+----------------------------------

  3. c4ca4238a0b923820dcc509a6f75849b | 96a17eccedd409b3b3de3b411d431ab8 | 1 | Eg1 DD+Hst | 2022-09-01 16:18:07.569818 | 2022-09-01 16:18:07.569818 | | 1 | 3bd474b8-0329-4bce-bde7-aee7c5d30cc8 | 2022-09-01 16:52:44.103+00 | 2022-09-01 17:03:37.521659+00 | 78812b56ae516cb4bb4278c595c3b20e

  4. c81e728d9d4c2f636f067f89cc14862c | 064c6bc6ac9c9956a7188495284d8c07 | 2 | Eg2a DD+Hs | 2022-09-01 16:30:13.93903 | 2022-09-01 16:30:13.93903 | 2022-09-01 17:02:14.841419 | 0 | 4282344a-62c3-4634-a91a-e6dafb9b253a | 2022-09-01 16:52:44.103+00 | 2022-09-01 17:03:37.521659+00 | d89c24a3d20ae9663d6f9a40f023149c

  5. c81e728d9d4c2f636f067f89cc14862c | 8d269939a7b0ae8c321d5f25d3be8619 | 2 | Eg2b DD+Hs | 2022-09-01 17:02:14.841419 | 2022-09-01 17:02:14.841419 | | 1 | 89377204-7801-49c8-a779-91da45a86cc3 | 2022-09-01 17:02:39.894+00 | 2022-09-01 17:03:37.521659+00 | 019e1ebcc8b9bb93c020422f7ba8313d

  6. (3 rows)

与同步前的历史记录表相比,值得强调的是,现在有两个 id 值为 2 的记录条目。id=2 的记录的新副本没有定义_airbyte_end_at值,它的_airbyte_active_row值为 1,这意味着它仍然处于活动状态。此记录的先前版本定义了 _airbyte_start_at 和_airbyte_end_at_airbyte_active_row值为 0,表示这是历史记录。

通过执行以下操作,查看目标中名为 table_two 的已消除重复数据表:

 
  
  1. SELECT * FROM table_two;

其外观如下:

 
  
  1. _airbyte_unique_key | id | name | updated_at | _airbyte_ab_id | _airbyte_emitted_at | _airbyte_normalized_at | _airbyte_table_two_hashid

  2. ----------------------------------+----+------------+----------------------------+--------------------------------------+----------------------------+-------------------------------+----------------------------------

  3. c4ca4238a0b923820dcc509a6f75849b | 1 | Eg1 DD+Hst | 2022-09-01 16:18:07.569818 | 3bd474b8-0329-4bce-bde7-aee7c5d30cc8 | 2022-09-01 16:52:44.103+00 | 2022-09-01 17:03:39.029637+00 | 78812b56ae516cb4bb4278c595c3b20e

  4. c81e728d9d4c2f636f067f89cc14862c | 2 | Eg2b DD+Hs | 2022-09-01 17:02:14.841419 | 89377204-7801-49c8-a779-91da45a86cc3 | 2022-09-01 17:02:39.894+00 | 2022-09-01 17:03:39.029637+00 | 019e1ebcc8b9bb93c020422f7ba8313d

  5. (2 rows)

请注意,即使历史表中有两个 id 为 2 的记录副本,此表中也只有一个副本,因为它已被消除重复。这是通过SQL实现的,SQL仅在_airbyte_active_row值为1时将记录从table_two_scd复制到table_two。这与以前在增量追加复制模式下看到的行为不同,后者导致更新记录的两个副本都存储在最终表中。

更新:查看 SQL

SQL 数据处理步骤概述

用于创建最终(重复数据删除)表和历史记录 (SCD) 表的 SQL 具有几个中间步骤,这些步骤使用公用表表达式(或 CTE)、一些临时表和临时表,如下图所示:

探索 Airbyte 的增量数据同步_第19张图片

临时表 SQL - 更新table_two_stg

现在,您将查看在初始化目标后用于增量历史记录 + 重复数据删除复制的 SQL。这与第一次迭代略有不同,因为记录入到现有表中,而不是创建新的目标表。使用最近同步中的作业 ID(在我的例子中为 171)和尝试 ID(在我的例子中为 0),您可以使用以下命令查看用于创建table_two_stg的 SQL:

 
  
  1. cat /tmp/workspace/171/0/build/run/airbyte_utils/models/generated/airbyte_incremental/public/table_two_stg.sql

这将返回以下 SQL。

 
  
  1. delete from "postgres"._airbyte_public."table_two_stg"

  2. where (_airbyte_ab_id) in (

  3. select (_airbyte_ab_id)

  4. from "table_two_stg__dbt_tmp140757456406"

  5. );

  6. insert into "postgres"._airbyte_public."table_two_stg" ("_airbyte_table_two_hashid", "id", "name", "updated_at", "_airbyte_ab_id", "_airbyte_emitted_at", "_airbyte_normalized_at")

  7. (

  8. select "_airbyte_table_two_hashid", "id", "name", "updated_at", "_airbyte_ab_id", "_airbyte_emitted_at", "_airbyte_normalized_at"

  9. from "table_two_stg__dbt_tmp140757456406"

  10. )

在高级别上,此 SQL 将所有记录从名为 table_two_stg__dbt_tmp140757456406 的临时表复制到table_two_stg。如果文档已存在于目标表中,并且该文档也出现在临时表中,则在将整个临时表插入目标表之前,可以通过将其从目标表中删除来避免重复。这与前面分析增量追加 SQL 时描述的逻辑相同。

主要逻辑在创建table_two_stg__dbt_tmp140757456406时执行,可以在与此同步关联的 dbt 日志文件中找到。这可以在 airbyte 服务器容器上使用以下命令查看:

 
  
  1. cat /tmp/workspace/171/0/logs/dbt.log

然后搜索日志以创建临时表table_two_stg__dbt_tmp140757456406。用于创建此临时表的代码如下所示:

 
  
  1. create temporary table "table_two_stg__dbt_tmp140757456406"

  2. as (

  3. with __dbt__cte__table_two_ab1 as (

  4. -- SQL model to parse JSON blob stored in a single column and extract into separated field columns as described by the JSON Schema

  5. -- depends_on: "postgres".public._airbyte_raw_table_two

  6. select

  7. jsonb_extract_path_text(_airbyte_data, 'id') as "id",

  8. jsonb_extract_path_text(_airbyte_data, 'name') as "name",

  9. jsonb_extract_path_text(_airbyte_data, 'updated_at') as updated_at,

  10. _airbyte_ab_id,

  11. _airbyte_emitted_at,

  12. now() as _airbyte_normalized_at

  13. from "postgres".public._airbyte_raw_table_two as table_alias

  14. -- table_two

  15. where 1 = 1

  16. ), __dbt__cte__table_two_ab2 as (

  17. -- SQL model to cast each column to its adequate SQL type converted from the JSON schema type

  18. -- depends_on: __dbt__cte__table_two_ab1

  19. select

  20. cast("id" as

  21. bigint

  22. ) as "id",

  23. cast("name" as text) as "name",

  24. cast(nullif(updated_at, '') as

  25. timestamp

  26. ) as updated_at,

  27. _airbyte_ab_id,

  28. _airbyte_emitted_at,

  29. now() as _airbyte_normalized_at

  30. from __dbt__cte__table_two_ab1

  31. -- table_two

  32. where 1 = 1

  33. )-- SQL model to build a hash column based on the values of this record

  34. -- depends_on: __dbt__cte__table_two_ab2

  35. select

  36. md5(cast(coalesce(cast("id" as text), '') || '-' || coalesce(cast("name" as text), '') || '-' || coalesce(cast(updated_at as text), '') as text)) as _airbyte_table_two_hashid,

  37. tmp.*

  38. from __dbt__cte__table_two_ab2 tmp

  39. -- table_two

  40. where 1 = 1

  41. and coalesce(

  42. cast(_airbyte_emitted_at as

  43. timestamp with time zone

  44. ) >= (select max(cast(_airbyte_emitted_at as

  45. timestamp with time zone

  46. )) from "postgres"._airbyte_public."table_two_stg"),

  47. true)

  48. );

此 SQL 与上一次同步中创建临时表时使用的 SQL 几乎相同。但是,主要区别在于末尾有一个额外的代码块,它减少了将处理的记录数,以仅包括最近同步中发送的记录以及上一次同步中的记录(如本期所述)。这是通过在目标表table_two_stg中查找最大的_airbyte_emitted_at值,并且仅从原始表中选择要_airbyte_emitted_at大于或等于此值的记录进行规范化来实现的。

历史记录表 SQL – 更新table_two_scd

通过在 airbyte 服务器容器中执行以下命令来查看创建历史记录表的 SQL:

 
  
  1. cat /tmp/workspace/171/0/build/run/airbyte_utils/models/generated/airbyte_incremental/scd/public/table_two_scd.sql

它使用以下 SQL 进行响应

 
  
  1. delete from "postgres".public."table_two_scd"

  2. where (_airbyte_unique_key_scd) in (

  3. select (_airbyte_unique_key_scd)

  4. from "table_two_scd__dbt_tmp140759296919"

  5. );

  6. insert into "postgres".public."table_two_scd" ("_airbyte_unique_key", "_airbyte_unique_key_scd", "id", "name", "updated_at", "_airbyte_start_at", "_airbyte_end_at", "_airbyte_active_row", "_airbyte_ab_id", "_airbyte_emitted_at", "_airbyte_normalized_at", "_airbyte_table_two_hashid")

  7. (

  8. select "_airbyte_unique_key", "_airbyte_unique_key_scd", "id", "name", "updated_at", "_airbyte_start_at", "_airbyte_end_at", "_airbyte_active_row", "_airbyte_ab_id", "_airbyte_emitted_at", "_airbyte_normalized_at", "_airbyte_table_two_hashid"

  9. from "table_two_scd__dbt_tmp140759296919"

  10. )

与前面部分中对 SQL 的分析类似,此名为 table_two_scd 的表通过将记录从临时表复制到其中来更新。主要逻辑是在创建名为 table_two_scd__dbt_tmp140759296919 的临时表时实现的,该表可以在 dbt 日志文件中找到,如下所示:

 
  
  1. cat /tmp/workspace/171/0/logs/dbt.log

并搜索临时表的创建(在本例中table_two_scd__dbt_tmp140759296919)。我将相关代码分成几个部分进行讨论。

SQL 的第一部分创建临时表,并通过比较临时表 (table_two_stg) _airbyte_emitted_at 中的时间戳与历史记录 (table_two_scd) 表中的时间戳,从临时表中选择table_two_scd中尚不存在的记录,以确定需要将哪些记录复制到名为 new_data 的公用表表达式 (CTE) 中。

 
  
  1. create temporary table "table_two_scd__dbt_tmp140759296919"

  2. as (

  3. -- depends_on: ref('table_two_stg')

  4. with

  5. new_data as (

  6. -- retrieve incremental "new" data

  7. select

  8. *

  9. from "postgres"._airbyte_public."table_two_stg"

  10. -- table_two from "postgres".public._airbyte_raw_table_two

  11. where 1 = 1

  12. and coalesce(

  13. cast(_airbyte_emitted_at as

  14. timestamp with time zone

  15. ) >= (select max(cast(_airbyte_emitted_at as

  16. timestamp with time zone

  17. )) from "postgres".public."table_two_scd"),

  18. true)

  19. ),

SQL 的下一部分存储新记录的名为 _airbyte_unique_key 的主键字段 (id) 的唯一哈希列表,并将它们存储在名为 new_data_ids 的 CTE 中,如下所示:

 
  
  1. new_data_ids as (

  2. -- build a subset of _airbyte_unique_key from rows that are new

  3. select distinct

  4. md5(cast(coalesce(cast("id" as text), '') as text)) as _airbyte_unique_key

  5. from new_data

  6. ),

  7. empty_new_data as (

  8. -- build an empty table to only keep the table's column types

  9. select * from new_data where 1 = 0

  10. ),

SQL 的下一部分将创建一个名为 previous_active_scd_data 的 CTE,该 CTE 选择现有历史记录表 (table_two_scd) 中需要额外 SQL 处理的记录。

 
  
  1. previous_active_scd_data as (

  2. -- retrieve "incomplete old" data that needs to be updated with an end date because of new changes

  3. select

  4. this_data."_airbyte_table_two_hashid",

  5. this_data."id",

  6. this_data."name",

  7. this_data."updated_at",

  8. this_data."_airbyte_ab_id",

  9. this_data."_airbyte_emitted_at",

  10. this_data."_airbyte_normalized_at"

  11. from "postgres".public."table_two_scd" as this_data

  12. -- make a join with new_data using primary key to filter active data that need to be updated only

  13. join new_data_ids on this_data._airbyte_unique_key = new_data_ids._airbyte_unique_key

  14. -- force left join to NULL values (we just need to transfer column types only for the star_intersect macro on schema changes)

  15. left join empty_new_data as inc_data on this_data._airbyte_ab_id = inc_data._airbyte_ab_id

  16. where _airbyte_active_row = 1

  17. ),

下一部分将创建一个名为 input_data 的 CTE,该 CTE 合并了名为 new_data(包含上次同步中插入的记录)和 previous_active_scd_data(包含需要更新的现有记录)的 CTE 中的记录如下所示:

 
  
  1. input_data as (

  2. select "_airbyte_table_two_hashid",

  3. "id",

  4. "name",

  5. "updated_at",

  6. "_airbyte_ab_id",

  7. "_airbyte_emitted_at",

  8. "_airbyte_normalized_at" from new_data

  9. union all

  10. select "_airbyte_table_two_hashid",

  11. "id",

  12. "name",

  13. "updated_at",

  14. "_airbyte_ab_id",

  15. "_airbyte_emitted_at",

  16. "_airbyte_normalized_at" from previous_active_scd_data

  17. ),

下一节定义了一个名为 scd_data 的 CTE,它基于刚刚创建的 input_data CTE 中的记录。此新 CTE 计算一个名为 _airbyte_end_at 的字段,该字段指示记录不再有效的时间。这是通过使用 lag 函数将给定记录的先前版本_airbyte_end_at设置为从该记录的较新版本获取的updated_at时间的值来计算的 – 实际上,如果存在记录的新副本,则该记录的先前版本从更新的那一刻起不再有效。它还将给定记录的最新条目设置为 _airbyte_active_row 到 1,对于其他条目设置为 0。

 
  
  1. scd_data as (

  2. -- SQL model to build a Type 2 Slowly Changing Dimension (SCD) table for each record identified by their primary key

  3. select

  4. md5(cast(coalesce(cast("id" as text), '') as text)) as _airbyte_unique_key,

  5. "id",

  6. "name",

  7. updated_at,

  8. updated_at as _airbyte_start_at,

  9. lag(updated_at) over (

  10. partition by cast("id" as text)

  11. order by

  12. updated_at is null asc,

  13. updated_at desc,

  14. _airbyte_emitted_at desc

  15. ) as _airbyte_end_at,

  16. case when row_number() over (

  17. partition by cast("id" as text)

  18. order by

  19. updated_at is null asc,

  20. updated_at desc,

  21. _airbyte_emitted_at desc

  22. ) = 1 then 1 else 0 end as _airbyte_active_row,

  23. _airbyte_ab_id,

  24. _airbyte_emitted_at,

  25. _airbyte_table_two_hashid

  26. from input_data

  27. ),

下一个 SQL 块使用上面显示 CTE scd_data作为其输入。它将记录划分为具有相同_airbyte_unique_key_airbyte_start_at_airbyte_emitted_at的组,并将它们按行排序。生成的行号将写入_airbyte_row_num,用于下一步中的重复数据删除。此 SQL 还根据多个字段计算_airbyte_unique_key_scd的值,如下所示。

 
  
  1. dedup_data as (

  2. select

  3. -- we need to ensure de-duplicated rows for merge/update queries

  4. -- additionally, we generate a unique key for the scd table

  5. row_number() over (

  6. partition by

  7. _airbyte_unique_key,

  8. _airbyte_start_at,

  9. _airbyte_emitted_at

  10. order by _airbyte_active_row desc, _airbyte_ab_id

  11. ) as _airbyte_row_num,

  12. md5(cast(coalesce(cast(_airbyte_unique_key as text), '') || '-' || coalesce(cast(_airbyte_start_at as text), '') || '-' || coalesce(cast(_airbyte_emitted_at as text), '') as text)) as _airbyte_unique_key_scd,

  13. scd_data.*

  14. from scd_data

  15. )

对于最终输出,SQL 仅从上面计算的 dedup_data CTE 中选择 _airbyte_row_num = 1 的记录,以确保给定记录的相同历史版本的重复不会写入临时表(因此不会写入基于临时表创建的table_two_scd

 
  
  1. select

  2. _airbyte_unique_key,

  3. _airbyte_unique_key_scd,

  4. "id",

  5. "name",

  6. updated_at,

  7. _airbyte_start_at,

  8. _airbyte_end_at,

  9. _airbyte_active_row,

  10. _airbyte_ab_id,

  11. _airbyte_emitted_at,

  12. now() as _airbyte_normalized_at,

  13. _airbyte_table_two_hashid

  14. from dedup_data where _airbyte_row_num = 1

  15. );

重复数据删除表 SQL - 更新table_two

最后table_two由SQL创建,可以通过执行来查看:

 
  
  1. cat /tmp/workspace/171/0/build/run/airbyte_utils/models/generated/airbyte_incremental/public/table_two.sql

哪个应该回应:

 
  
  1. delete from "postgres".public."table_two"

  2. where (_airbyte_unique_key) in (

  3. select (_airbyte_unique_key)

  4. from "table_two__dbt_tmp140800091278"

  5. );

  6. insert into "postgres".public."table_two" ("_airbyte_unique_key", "id", "name", "updated_at", "_airbyte_ab_id", "_airbyte_emitted_at", "_airbyte_normalized_at", "_airbyte_table_two_hashid")

  7. (

  8. select "_airbyte_unique_key", "id", "name", "updated_at", "_airbyte_ab_id", "_airbyte_emitted_at", "_airbyte_normalized_at", "_airbyte_table_two_hashid"

  9. from "table_two__dbt_tmp140800091278"

  10. )

同样,这是将记录从临时表复制到table_two的 SQL,主要工作是在创建临时表的逻辑中完成的。在此示例中,临时表称为 table_two__dbt_tmp140800091278,可以通过执行以下命令在 dbt 日志中找到其创建:

 
  
  1. cat /tmp/workspace/171/0/logs/dbt.log

搜索名为table_two__dbt_tmp140800091278代码的表的创建如下所示:

 
  
  1. create temporary table "table_two__dbt_tmp140800091278"

  2. as (

  3. -- Final base SQL model

  4. -- depends_on: "postgres".public."table_two_scd"

  5. select

  6. _airbyte_unique_key,

  7. "id",

  8. "name",

  9. updated_at,

  10. _airbyte_ab_id,

  11. _airbyte_emitted_at,

  12. now() as _airbyte_normalized_at,

  13. _airbyte_table_two_hashid

  14. from "postgres".public."table_two_scd"

  15. -- table_two from "postgres".public._airbyte_raw_table_two

  16. where 1 = 1

  17. and _airbyte_active_row = 1

  18. and coalesce(

  19. cast(_airbyte_emitted_at as

  20. timestamp with time zone

  21. ) >= (select max(cast(_airbyte_emitted_at as

  22. timestamp with time zone

  23. )) from "postgres".public."table_two"),

  24. true)

  25. );

仅当 _airbyte_emitted_at 的值大于或等于已写入table_two的最高_airbyte_emitted_at值时,此代码才会从table_two_scd中选择被视为活动行_airbyte_active_row如值 1 所示。同样,这意味着当前同步和上一次同步的记录将被规范化。

插入:概述

在此步骤中,您将在源表中插入 id 为 3 的新记录。此新记录将被复制到目标并追加到原始数据表中,然后规范化为历史记录和重复数据删除表,如下所示:

插入:在源中写入新记录

返回到本教程前面打开的 airbyte-source 容器中的 Postgres shell,并将新记录插入table_two并按如下所示查看它:

 
  
  1. INSERT INTO table_two(id, name) VALUES(3, 'Eg3 DD+Hst');

  2. SELECT * FROM table_two;

table_two表应如下所示:

 
  
  1. id | name | updated_at

  2. ----+------------+----------------------------

  3. 1 | Eg1 DD+Hst | 2022-09-01 16:18:07.569818

  4. 2 | Eg2b DD+Hs | 2022-09-01 17:02:14.841419

  5. 3 | Eg3 DD+Hst | 2022-09-01 17:05:19.570672

  6. (3 rows)

通过单击连接 UI 中的“立即同步”来执行新的同步,然后等待同步完成。您应该会看到一个响应,指示已发出一条记录,如下所示:

插入:查看目标原始表

通过执行以下命令,查看增量重复数据删除历史记录同步到名为 _airbyte_raw_table_two 的原始表中的内容:

 
  
  1. SELECT * FROM _airbyte_raw_table_two;

它应该响应一个表,如下所示:

 
  
  1. _airbyte_ab_id | _airbyte_data | _airbyte_emitted_at

  2. --------------------------------------+-----------------------------------------------------------------------------+----------------------------

  3. 3bd474b8-0329-4bce-bde7-aee7c5d30cc8 | {"id": 1, "name": "Eg1 DD+Hst", "updated_at": "2022-09-01T16:18:07.569818"} | 2022-09-01 16:52:44.103+00

  4. 4282344a-62c3-4634-a91a-e6dafb9b253a | {"id": 2, "name": "Eg2a DD+Hs", "updated_at": "2022-09-01T16:30:13.939030"} | 2022-09-01 16:52:44.103+00

  5. 89377204-7801-49c8-a779-91da45a86cc3 | {"id": 2, "name": "Eg2b DD+Hs", "updated_at": "2022-09-01T17:02:14.841419"} | 2022-09-01 17:02:39.894+00

  6. 18ad74f5-ba91-4b23-bc78-b2b604bb1696 | {"id": 3, "name": "Eg3 DD+Hst", "updated_at": "2022-09-01T17:05:19.570672"} | 2022-09-01 17:05:44.49+00

  7. (4 rows)

插入:查看目标中的规范化表

通过执行以下命令查看名为 table_two_scd 的历史记录表:

 
  
  1. SELECT * FROM table_two_scd;

其中包括刚刚添加到源表中的记录,如下所示。

 
  
  1. _airbyte_unique_key | _airbyte_unique_key_scd | id | name | updated_at | _airbyte_start_at | _airbyte_end_at | _airbyte_active_row | _airbyte_ab_id | _airbyte_emitted_at | _airbyte_normalized_at | _airbyte_table_two_hashid

  2. ----------------------------------+----------------------------------+----+------------+----------------------------+----------------------------+----------------------------+---------------------+--------------------------------------+----------------------------+-------------------------------+----------------------------------

  3. c4ca4238a0b923820dcc509a6f75849b | 96a17eccedd409b3b3de3b411d431ab8 | 1 | Eg1 DD+Hst | 2022-09-01 16:18:07.569818 | 2022-09-01 16:18:07.569818 | | 1 | 3bd474b8-0329-4bce-bde7-aee7c5d30cc8 | 2022-09-01 16:52:44.103+00 | 2022-09-01 17:03:37.521659+00 | 78812b56ae516cb4bb4278c595c3b20e

  4. c81e728d9d4c2f636f067f89cc14862c | 064c6bc6ac9c9956a7188495284d8c07 | 2 | Eg2a DD+Hs | 2022-09-01 16:30:13.93903 | 2022-09-01 16:30:13.93903 | 2022-09-01 17:02:14.841419 | 0 | 4282344a-62c3-4634-a91a-e6dafb9b253a | 2022-09-01 16:52:44.103+00 | 2022-09-01 17:03:37.521659+00 | d89c24a3d20ae9663d6f9a40f023149c

  5. c81e728d9d4c2f636f067f89cc14862c | 8d269939a7b0ae8c321d5f25d3be8619 | 2 | Eg2b DD+Hs | 2022-09-01 17:02:14.841419 | 2022-09-01 17:02:14.841419 | | 1 | 89377204-7801-49c8-a779-91da45a86cc3 | 2022-09-01 17:02:39.894+00 | 2022-09-01 17:06:41.92607+00 | 019e1ebcc8b9bb93c020422f7ba8313d

  6. eccbc87e4b5ce2fe28308fd9f2a7baf3 | f3dfb89e70d5712b62b4b4baf10cf04c | 3 | Eg3 DD+Hst | 2022-09-01 17:05:19.570672 | 2022-09-01 17:05:19.570672 | | 1 | 18ad74f5-ba91-4b23-bc78-b2b604bb1696 | 2022-09-01 17:05:44.49+00 | 2022-09-01 17:06:41.92607+00 | 0845d83977c1cdd5464c31cc1f03a649

  7. (4 rows)

通过执行以下命令查看重复数据删除表的内容:

 
  
  1. SELECT * FROM table_two;

重复数据删除的table_two表如下所示,并且具有与源表中每条记录对应的一条记录。

 
  
  1. _airbyte_unique_key | id | name | updated_at | _airbyte_ab_id | _airbyte_emitted_at | _airbyte_normalized_at | _airbyte_table_two_hashid

  2. ----------------------------------+----+------------+----------------------------+--------------------------------------+----------------------------+-------------------------------+----------------------------------

  3. c4ca4238a0b923820dcc509a6f75849b | 1 | Eg1 DD+Hst | 2022-09-01 16:18:07.569818 | 3bd474b8-0329-4bce-bde7-aee7c5d30cc8 | 2022-09-01 16:52:44.103+00 | 2022-09-01 17:03:39.029637+00 | 78812b56ae516cb4bb4278c595c3b20e

  4. c81e728d9d4c2f636f067f89cc14862c | 2 | Eg2b DD+Hs | 2022-09-01 17:02:14.841419 | 89377204-7801-49c8-a779-91da45a86cc3 | 2022-09-01 17:02:39.894+00 | 2022-09-01 17:06:43.486086+00 | 019e1ebcc8b9bb93c020422f7ba8313d

  5. eccbc87e4b5ce2fe28308fd9f2a7baf3 | 3 | Eg3 DD+Hst | 2022-09-01 17:05:19.570672 | 18ad74f5-ba91-4b23-bc78-b2b604bb1696 | 2022-09-01 17:05:44.49+00 | 2022-09-01 17:06:43.486086+00 | 0845d83977c1cdd5464c31cc1f03a649

  6. (3 rows)

插入:查看 SQL

用于此同步操作和所有后续同步操作的 SQL 与第二次同步操作期间使用的 SQL 相同(在本教程中为更新后上一节中完成的同步)。好奇的读者可以通过查看上一节中演示的 SQL,并使用作业 ID(本例中为 172)和尝试 ID(本例中为 0)来验证这一点,这些 ID 可以从 Airbyte 的 UI 中提取,如前所述。以下命令可用作 airbyte 服务器容器的起点,以查看为此同步执行的 SQL:

 
  
  1. cat /tmp/workspace/172/0/build/run/airbyte_utils/models/generated/airbyte_incremental/public/table_two_stg.sql

 
  
  1. cat /tmp/workspace/172/0/build/run/airbyte_utils/models/generated/airbyte_incremental/scd/public/table_two_scd.sql

 
  
  1. cat /tmp/workspace/172/0/build/run/airbyte_utils/models/generated/airbyte_incremental/public/table_two.sql

 
  
  1. cat /tmp/workspace/172/0/logs/dbt.log

i️ 由于此同步的 SQL 和所有后续同步与上一次同步相同,因此我在这里不详细讨论。

删除:概述

现在,您将从源表中删除记录,但如前所述,增量同步复制模式不会传播删除操作。如下图所示:

删除:从源中删除记录

从源中删除记录,如下所示:

 
  
  1. DELETE FROM table_two where id=3;

  2. SELECT * FROM table_two;

table_two表应如下所示:

 
  
  1. id | name | updated_at

  2. ----+------------+----------------------------

  3. 1 | Eg1 DD+Hst | 2022-09-01 16:18:07.569818

  4. 2 | Eg2b DD+Hs | 2022-09-01 17:02:14.841419

  5. (2 rows)

您应该看到 id 为 3 的新记录已从源表中删除。通过单击连接 UI 中的“立即同步”来执行新的同步,然后等待同步完成。

删除:查看目标中的原始表

通过执行以下命令,查看增量重复数据删除历史记录同步到名为 _airbyte_raw_table_two 的原始表中的内容:

 
  
  1. SELECT * FROM _airbyte_raw_table_two;

它应该响应一个表,如下所示:

 
  
  1. _airbyte_ab_id | _airbyte_data | _airbyte_emitted_at

  2. --------------------------------------+-----------------------------------------------------------------------------+----------------------------

  3. 3bd474b8-0329-4bce-bde7-aee7c5d30cc8 | {"id": 1, "name": "Eg1 DD+Hst", "updated_at": "2022-09-01T16:18:07.569818"} | 2022-09-01 16:52:44.103+00

  4. 4282344a-62c3-4634-a91a-e6dafb9b253a | {"id": 2, "name": "Eg2a DD+Hs", "updated_at": "2022-09-01T16:30:13.939030"} | 2022-09-01 16:52:44.103+00

  5. 89377204-7801-49c8-a779-91da45a86cc3 | {"id": 2, "name": "Eg2b DD+Hs", "updated_at": "2022-09-01T17:02:14.841419"} | 2022-09-01 17:02:39.894+00

  6. 18ad74f5-ba91-4b23-bc78-b2b604bb1696 | {"id": 3, "name": "Eg3 DD+Hst", "updated_at": "2022-09-01T17:05:19.570672"} | 2022-09-01 17:05:44.49+00

  7. (4 rows)

请注意,此表与从源系统中删除记录之前完全相同 – 换句话说,在源系统中删除的记录仍存在于目标中。如前所述,增量同步模式不会将删除从源数据库传播到目标数据库,因此这是预期行为。

删除:查看目标中的规范化表

通过执行以下命令查看名为 table_two_scd 的历史记录表:

 
  
  1. SELECT * FROM table_two_scd;

其中包括刚刚添加到源表中的记录,如下所示。

 
  
  1. _airbyte_unique_key | _airbyte_unique_key_scd | id | name | updated_at | _airbyte_start_at | _airbyte_end_at | _airbyte_active_row | _airbyte_ab_id | _airbyte_emitted_at | _airbyte_normalized_at | _airbyte_table_two_hashid

  2. ----------------------------------+----------------------------------+----+------------+----------------------------+----------------------------+----------------------------+---------------------+--------------------------------------+----------------------------+-------------------------------+----------------------------------

  3. c4ca4238a0b923820dcc509a6f75849b | 96a17eccedd409b3b3de3b411d431ab8 | 1 | Eg1 DD+Hst | 2022-09-01 16:18:07.569818 | 2022-09-01 16:18:07.569818 | | 1 | 3bd474b8-0329-4bce-bde7-aee7c5d30cc8 | 2022-09-01 16:52:44.103+00 | 2022-09-01 17:03:37.521659+00 | 78812b56ae516cb4bb4278c595c3b20e

  4. c81e728d9d4c2f636f067f89cc14862c | 064c6bc6ac9c9956a7188495284d8c07 | 2 | Eg2a DD+Hs | 2022-09-01 16:30:13.93903 | 2022-09-01 16:30:13.93903 | 2022-09-01 17:02:14.841419 | 0 | 4282344a-62c3-4634-a91a-e6dafb9b253a | 2022-09-01 16:52:44.103+00 | 2022-09-01 17:03:37.521659+00 | d89c24a3d20ae9663d6f9a40f023149c

  5. c81e728d9d4c2f636f067f89cc14862c | 8d269939a7b0ae8c321d5f25d3be8619 | 2 | Eg2b DD+Hs | 2022-09-01 17:02:14.841419 | 2022-09-01 17:02:14.841419 | | 1 | 89377204-7801-49c8-a779-91da45a86cc3 | 2022-09-01 17:02:39.894+00 | 2022-09-01 17:06:41.92607+00 | 019e1ebcc8b9bb93c020422f7ba8313d

  6. eccbc87e4b5ce2fe28308fd9f2a7baf3 | f3dfb89e70d5712b62b4b4baf10cf04c | 3 | Eg3 DD+Hst | 2022-09-01 17:05:19.570672 | 2022-09-01 17:05:19.570672 | | 1 | 18ad74f5-ba91-4b23-bc78-b2b604bb1696 | 2022-09-01 17:05:44.49+00 | 2022-09-01 17:23:28.007869+00 | 0845d83977c1cdd5464c31cc1f03a649

  7. (4 rows)

此表与最近同步之前的状态几乎相同,但 _airbyte_normalized_at 值除外,该值指示即使没有更新任何记录,但无论如何,最新的记录都已规范化。

通过执行以下命令查看重复数据删除表的内容:

 
  
  1. SELECT * FROM table_two;

重复数据删除的table_two表如下所示,并且具有与源表中每条记录对应的一条记录。

 
  
  1. _airbyte_unique_key | id | name | updated_at | _airbyte_ab_id | _airbyte_emitted_at | _airbyte_normalized_at | _airbyte_table_two_hashid

  2. ----------------------------------+----+------------+----------------------------+--------------------------------------+----------------------------+-------------------------------+----------------------------------

  3. c4ca4238a0b923820dcc509a6f75849b | 1 | Eg1 DD+Hst | 2022-09-01 16:18:07.569818 | 3bd474b8-0329-4bce-bde7-aee7c5d30cc8 | 2022-09-01 16:52:44.103+00 | 2022-09-01 17:03:39.029637+00 | 78812b56ae516cb4bb4278c595c3b20e

  4. c81e728d9d4c2f636f067f89cc14862c | 2 | Eg2b DD+Hs | 2022-09-01 17:02:14.841419 | 89377204-7801-49c8-a779-91da45a86cc3 | 2022-09-01 17:02:39.894+00 | 2022-09-01 17:06:43.486086+00 | 019e1ebcc8b9bb93c020422f7ba8313d

  5. eccbc87e4b5ce2fe28308fd9f2a7baf3 | 3 | Eg3 DD+Hst | 2022-09-01 17:05:19.570672 | 18ad74f5-ba91-4b23-bc78-b2b604bb1696 | 2022-09-01 17:05:44.49+00 | 2022-09-01 17:23:29.577994+00 | 0845d83977c1cdd5464c31cc1f03a649

  6. (3 rows)

此表也与此同步之前显示的表基本相同,尽管_airbyte_normalized_at值已按预期更新。换句话说,源中删除的记录尚未在目标表中删除(如预期的那样)。

删除:查看 SQL

此同步的 SQL 与上一次同步相同,因此无需进一步讨论。

无需任何修改即可同步:概述

在不修改源数据的情况下执行同步后,不会将任何数据从源传输到目标,并且数据表看起来与同步操作之前相同,如下所示。

同步无需任何修改

如果在未对源数据库进行任何修改的情况下执行同步,则不会发出任何记录,也不会对目标数据库进行任何更改。您可以通过单击“立即同步”,然后验证是否未发出任何记录来确认这一点,如下所示。

无需任何修改即可同步:查看目标中的原始表

原始数据的显示方式将与同步前完全相同。这可以通过执行如下所示的命令来看到:

 
  
  1. SELECT * FROM _airbyte_raw_table_two;

它应该响应一个如下所示的表:

 
  
  1. _airbyte_ab_id | _airbyte_data | _airbyte_emitted_at

  2. --------------------------------------+-----------------------------------------------------------------------------+----------------------------

  3. 3bd474b8-0329-4bce-bde7-aee7c5d30cc8 | {"id": 1, "name": "Eg1 DD+Hst", "updated_at": "2022-09-01T16:18:07.569818"} | 2022-09-01 16:52:44.103+00

  4. 4282344a-62c3-4634-a91a-e6dafb9b253a | {"id": 2, "name": "Eg2a DD+Hs", "updated_at": "2022-09-01T16:30:13.939030"} | 2022-09-01 16:52:44.103+00

  5. 89377204-7801-49c8-a779-91da45a86cc3 | {"id": 2, "name": "Eg2b DD+Hs", "updated_at": "2022-09-01T17:02:14.841419"} | 2022-09-01 17:02:39.894+00

  6. 18ad74f5-ba91-4b23-bc78-b2b604bb1696 | {"id": 3, "name": "Eg3 DD+Hst", "updated_at": "2022-09-01T17:05:19.570672"} | 2022-09-01 17:05:44.49+00

同步而不进行任何修改:查看目标中的规范化表

通过执行以下命令查看名为 table_two_scd 的历史记录表:

 
  
  1. SELECT * FROM table_two_scd;

如下所示。

 
  
  1. _airbyte_unique_key | _airbyte_unique_key_scd | id | name | updated_at | _airbyte_start_at | _airbyte_end_at | _airbyte_active_row | _airbyte_ab_id | _airbyte_emitted_at | _airbyte_normalized_at | _airbyte_table_two_hashid

  2. ----------------------------------+----------------------------------+----+------------+----------------------------+----------------------------+----------------------------+---------------------+--------------------------------------+----------------------------+-------------------------------+----------------------------------

  3. c4ca4238a0b923820dcc509a6f75849b | 96a17eccedd409b3b3de3b411d431ab8 | 1 | Eg1 DD+Hst | 2022-09-01 16:18:07.569818 | 2022-09-01 16:18:07.569818 | | 1 | 3bd474b8-0329-4bce-bde7-aee7c5d30cc8 | 2022-09-01 16:52:44.103+00 | 2022-09-01 17:03:37.521659+00 | 78812b56ae516cb4bb4278c595c3b20e

  4. c81e728d9d4c2f636f067f89cc14862c | 064c6bc6ac9c9956a7188495284d8c07 | 2 | Eg2a DD+Hs | 2022-09-01 16:30:13.93903 | 2022-09-01 16:30:13.93903 | 2022-09-01 17:02:14.841419 | 0 | 4282344a-62c3-4634-a91a-e6dafb9b253a | 2022-09-01 16:52:44.103+00 | 2022-09-01 17:03:37.521659+00 | d89c24a3d20ae9663d6f9a40f023149c

  5. c81e728d9d4c2f636f067f89cc14862c | 8d269939a7b0ae8c321d5f25d3be8619 | 2 | Eg2b DD+Hs | 2022-09-01 17:02:14.841419 | 2022-09-01 17:02:14.841419 | | 1 | 89377204-7801-49c8-a779-91da45a86cc3 | 2022-09-01 17:02:39.894+00 | 2022-09-01 17:06:41.92607+00 | 019e1ebcc8b9bb93c020422f7ba8313d

  6. eccbc87e4b5ce2fe28308fd9f2a7baf3 | f3dfb89e70d5712b62b4b4baf10cf04c | 3 | Eg3 DD+Hst | 2022-09-01 17:05:19.570672 | 2022-09-01 17:05:19.570672 | | 1 | 18ad74f5-ba91-4b23-bc78-b2b604bb1696 | 2022-09-01 17:05:44.49+00 | 2022-09-01 17:32:20.158788+00 | 0845d83977c1cdd5464c31cc1f03a649

  7. (4 rows)

请注意,历史表再次与同步之前几乎相同,但 _airbyte_normalized_at 除外,这表示此记录已重新生成。

通过执行以下操作,查看目标中名为 table_two 的已消除重复数据表:

 
  
  1. SELECT * FROM table_two;

其外观如下:

 
  
  1. _airbyte_unique_key | id | name | updated_at | _airbyte_ab_id | _airbyte_emitted_at | _airbyte_normalized_at | _airbyte_table_two_hashid

  2. ----------------------------------+----+------------+----------------------------+--------------------------------------+----------------------------+-------------------------------+----------------------------------

  3. c4ca4238a0b923820dcc509a6f75849b | 1 | Eg1 DD+Hst | 2022-09-01 16:18:07.569818 | 3bd474b8-0329-4bce-bde7-aee7c5d30cc8 | 2022-09-01 16:52:44.103+00 | 2022-09-01 17:03:39.029637+00 | 78812b56ae516cb4bb4278c595c3b20e

  4. c81e728d9d4c2f636f067f89cc14862c | 2 | Eg2b DD+Hs | 2022-09-01 17:02:14.841419 | 89377204-7801-49c8-a779-91da45a86cc3 | 2022-09-01 17:02:39.894+00 | 2022-09-01 17:06:43.486086+00 | 019e1ebcc8b9bb93c020422f7ba8313d

  5. eccbc87e4b5ce2fe28308fd9f2a7baf3 | 3 | Eg3 DD+Hst | 2022-09-01 17:05:19.570672 | 18ad74f5-ba91-4b23-bc78-b2b604bb1696 | 2022-09-01 17:05:44.49+00 | 2022-09-01 17:32:21.63737+00 | 0845d83977c1cdd5464c31cc1f03a649

  6. (3 rows)

请注意,重复数据删除的数据再次与同步之前的数据几乎相同,但 _airbyte_normalized_at 除外,这表示此记录已重新生成。

结论

在本教程中,我将指导您深入了解 Airbyte 的增量同步模式。本文的主要重点是了解如何选择数据进行复制,复制的数据的外观,以及了解为将原始数据转换为规范化数据而执行的 SQL 代码。

与完全刷新模式相比,使用 Airbyte 的增量同步模式通常更可取,因为每次同步操作时复制的数据(通常非常大)减少,这可能会导致效率的巨大提高。但是,应该注意的是,在使用增量同步时,由于选择记录进行复制的方式,删除的记录不会传播到目标。如果使用增量复制,则通过使用软删除来传播删除操作可能是可行的。或者,可以将更改数据捕获 (CDC) 复制视为增量同步的替代方法,因为它可确保删除操作从源正确传播到目标。

你可能感兴趣的:(etl,数据仓库)