Skip to content
ClickHouse Docs
ClickHouse DocsClickHouse Docs

处理 TOAST 列

在将数据从 PostgreSQL 复制到 ClickHouse 时,了解 TOAST (超大属性存储技术) 列的局限性及其特殊处理要求非常重要。本指南将帮助您在复制过程中识别并妥善处理 TOAST 列。

PostgreSQL 中的 TOAST 列是什么?

TOAST (The Oversized-Attribute Storage Technique) 是 PostgreSQL 处理大型字段值的机制。当某一行超过最大行大小时 (通常为 2KB,但具体取决于 PostgreSQL 版本和实际配置) ,PostgreSQL 会自动将较大的字段值移到单独的 TOAST 表中,在主表中只保留一个指针。

需要注意的是,在 CDC (变更数据捕获) 过程中,未发生变化的 TOAST 列不会包含在复制流中。如果处理不当,可能会导致复制的数据不完整。

在初始加载 (snapshot) 期间,所有列值 (包括 TOAST 列) 都会被正确复制,不受其大小影响。本指南中提到的限制,主要影响初始加载完成后持续进行的 CDC 过程。

你可以在此处进一步了解 TOAST 及其在 PostgreSQL 中的实现方式:https://www.postgresql.org/docs/current/storage-toast.html

识别表中的 TOAST 列

要判断表中是否存在 TOAST 列,可以使用以下 SQL 查询:

SELECT a.attname, pg_catalog.format_type(a.atttypid, a.atttypmod) AS data_type
FROM pg_attribute a
JOIN pg_class c ON a.attrelid = c.oid
WHERE c.relname = 'your_table_name'
  AND a.attlen = -1
  AND a.attstorage != 'p'
  AND a.attnum > 0;

此查询将返回可能会被 TOAST 化的列名及其数据类型。不过,需要注意的是,该查询仅根据数据类型和存储属性识别出具备 TOAST 存储条件的列。要判断这些列是否确实包含 TOAST 化的数据,还需要看这些列中的值是否超过大小限制。数据是否会实际发生 TOAST 化,取决于这些列中存储的具体内容。

确保正确处理 TOAST 列

为确保在复制过程中正确处理 TOAST 列,应将该表的 REPLICA IDENTITY 设置为 FULL。这会告知 PostgreSQL 在执行 UPDATE 和 DELETE 操作时,将完整的旧行写入 WAL,从而确保所有列值 (包括 TOAST 列) 都可用于复制。

你可以使用以下 SQL 命令将 REPLICA IDENTITY 设置为 FULL

ALTER TABLE your_table_name REPLICA IDENTITY FULL;

有关设置 REPLICA IDENTITY FULL 时的性能考量,请参阅这篇博文

未设置 REPLICA IDENTITY FULL 时的复制行为

如果某个包含 TOAST 列的表没有设置 REPLICA IDENTITY FULL,在复制到 ClickHouse 时,可能会出现以下问题:

  1. 在 INSERT 操作中,所有列 (包括 TOAST 列) 都会被正确复制。

  2. 在 UPDATE 操作中:

    • 如果 TOAST 列未被修改,其值在 ClickHouse 中会显示为 NULL 或空值。
    • 如果 TOAST 列被修改,则会被正确复制。
  3. 在 DELETE 操作中,TOAST 列的值在 ClickHouse 中会显示为 NULL 或空值。

这些情况可能会导致 PostgreSQL 源端与 ClickHouse 目标端之间的数据不一致。因此,对于包含 TOAST 列的表,务必设置 REPLICA IDENTITY FULL,以确保数据复制准确完整。

结论

在从 PostgreSQL 复制到 ClickHouse 的过程中,正确处理 TOAST 列对于维护数据完整性至关重要。通过识别 TOAST 列并设置适当的 REPLICA IDENTITY,可以确保数据得到准确、完整的复制。

Navigation