从 PostgreSQL 到数据仓库:近实时 ETL / 数据提取的最佳方法
Posted
技术标签:
【中文标题】从 PostgreSQL 到数据仓库:近实时 ETL / 数据提取的最佳方法【英文标题】:PostgreSQL to Data-Warehouse: Best approach for near-real-time ETL / extraction of data 【发布时间】:2010-03-25 22:45:21 【问题描述】:背景:
我有一个针对 OLTP 进行了高度优化的 PostgreSQL (v8.3) 数据库。
我需要在半实时的基础上从中提取数据(有人一定会问半实时是什么意思,答案是尽可能频繁,但我会务实,作为基准假设我们希望每 15 分钟)并将其输入数据仓库。
多少数据?在高峰期,我们谈论每分钟大约 80-100k 行到达 OLTP 端,非高峰期这将显着下降到 15-20k。最频繁更新的行每行约为 64 字节,但有各种表等,因此数据非常多样化,每行最多可达 4000 字节。 OLTP 24x5.5 全天候运行。
最佳解决方案?
据我所知,最实用的解决方案如下:
创建一个触发器以将所有 DML 活动写入一个循环的 CSV 日志文件 执行任何需要的转换 使用原生 DW 数据泵工具将转换后的 CSV 高效地泵入 DW为什么采用这种方法?
TRIGGERS 允许将选择性表作为目标而不是系统范围 + 输出是可配置的(即到 CSV),并且相对容易编写和部署。 SLONY 使用类似的方法,开销是可以接受的 CSV 转换简单快速 轻松将 CSV 泵入 DW考虑的替代方案....
使用本机日志记录 (http://www.postgresql.org/docs/8.3/static/runtime-config-logging.html)。问题在于它相对于我需要的东西看起来非常冗长,并且解析和转换有点棘手。但是,它可能会更快,因为我认为与 TRIGGER 相比开销更少。当然,因为它是系统范围的,所以它会使管理员更容易,但同样,我不需要某些表(有些用于持久存储我不想记录的 JMS 消息) 直接通过 Talend 等 ETL 工具查询数据并将其输入 DW ...问题是 OLTP 架构需要调整以支持这一点,并且会产生许多负面影响 使用经过调整/破解的 SLONY - SLONY 可以很好地记录并将更改迁移到从属设备,因此概念框架已经存在,但建议的解决方案似乎更简单、更清晰 使用 WAL以前有人做过吗?想分享你的想法吗?
【问题讨论】:
你最后用了什么? 【参考方案1】:假设您感兴趣的表具有(或可以增加)一个唯一的、索引的、顺序键,那么您将通过简单地将SELECT ... FROM table ... WHERE key > :last_max_key
输出到文件中获得更好的价值,其中last_max_key
是上次提取的最后一个键值(如果是第一次提取,则为 0。)这种增量解耦方法避免在插入数据路径中引入触发延迟(无论是自定义触发器还是修改的触发器) Slony),并且根据您的设置可以更好地扩展 CPU 数量等。(但是,如果您还必须跟踪 UPDATE
s,并且您添加了顺序键,那么您的 @ 987654324@ 语句应该 SET
成为 NULL
的键列,因此它会获得一个新值并在下一次提取时被选中。如果没有触发器,您将无法跟踪 DELETE
s。 ) 当你提到 Talend 时,这就是你的想法吗?
除非您无法实施上述解决方案,否则我会不使用日志记录工具;日志记录很可能涉及锁定开销,以确保日志行按顺序写入,并且在多个后端写入日志时不会相互重叠/覆盖(检查 Postgres 源。)锁定开销可能不是灾难性的,但如果您可以使用增量 SELECT
替代方案,则可以不使用它。此外,语句记录会淹没任何有用的 WARNING 或 ERROR 消息,并且解析本身不会是即时的。
除非您愿意解析 WAL(包括事务状态跟踪,并准备好在每次升级 Postgres 时重写代码),否则我也不一定会使用 WAL——也就是说,除非您拥有额外的硬件可用,在这种情况下,您可以将 WAL 发送到另一台机器进行提取(在第二台机器上,您可以无耻地使用触发器 -- 甚至是语句记录 --因为无论发生什么都不会影响INSERT
/UPDATE
/DELETE
主机上的性能。)请注意性能方面(在主机上),除非您可以将日志写入 SAN,否则您会从将 WAL 传送到不同的机器与运行增量 SELECT
相比,获得了相当的性能损失(主要是在文件系统缓存方面)。
【讨论】:
Talend 选项将采用您建议的方法……也许我应该重新考虑一下。但是您强调了关键问题,即跟踪 INSERT 和 UPDATE 和 DELETE。因此,无论我做什么,都需要做一些工作才能让它干净高效地工作……很惊讶这不是一个很常见的问题,网络上有很多例子。感谢您深思熟虑的回复。 主键阈值想法的一个潜在问题是 postgres 序列是非事务性的。也就是说,以较低 PK 插入的事务可能会在以较高 PK 插入的事务之后提交。因此,您的 ETL 策略可能会“错过”插入(假设为read committed
隔离级别)。这很少会成为问题(除非您有巨大的插入量或长事务),但如果您不能容忍 ETL 期间的数据丢失,则需要考虑这一点。【参考方案2】:
如果您能想到一个仅包含 id 和“校验和”的“校验和表”,您不仅可以快速选择新记录,还可以快速选择更改和删除的记录。
校验和可以是你喜欢的 crc32 校验和函数。
【讨论】:
我不知道为什么没有更多的讨论这个解决方案,这是很多平台的一个非常常见的解决方案。【参考方案3】:PostgreSQL 中的新 ON CONFLICT 子句改变了我进行许多更新的方式。我将新数据(基于 row_update_timestamp)拉到一个临时表中,然后在一个 SQL 语句中使用 ON CONFLICT UPDATE 将其插入到目标表中。如果您的目标表是分区的,那么您需要跳过几圈(即直接点击分区表)。 ETL 可能在您加载 Temp 表(最有可能)或 ON CONFLICT SQL(如果微不足道)时发生。与其他“UPSERT”系统(更新、零行时插入等)相比,这显示了巨大的速度提升。在我们特定的 DW 环境中,我们不需要/不想容纳 DELETE。查看 ON CONFLICT 文档 - 它让 Oracle 的 MERGE 物有所值!
【讨论】:
以上是关于从 PostgreSQL 到数据仓库:近实时 ETL / 数据提取的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章