PostgreSQL到数据仓库:近实时ETL/数据提取的最佳方法

PostgreSQL到数据仓库:近实时ETL/数据提取的最佳方法,postgresql,data-warehouse,etl,near-real-time,data-extraction,Postgresql,Data Warehouse,Etl,Near Real Time,Data Extraction,背景: 我有一个针对OLTP进行了大量优化的PostgreSQL(v8.3)数据库 我需要在半实时的基础上从中提取数据(有人一定会问半实时意味着什么,答案尽可能频繁,但我会务实,比如说,我们希望每15分钟一次),并将其输入数据仓库 有多少数据?在高峰时间,我们所说的每分钟大约80-100k行到达OLTP侧,非高峰时间将显著下降到15-20k。最频繁更新的行每行约64字节,但有各种表等,因此数据非常多样化,每行最多可更新4000字节。OLTP是活动的24x5.5 最佳解决方案? 从我能拼凑出的最实

背景:

我有一个针对OLTP进行了大量优化的PostgreSQL(v8.3)数据库

我需要在半实时的基础上从中提取数据(有人一定会问半实时意味着什么,答案尽可能频繁,但我会务实,比如说,我们希望每15分钟一次),并将其输入数据仓库

有多少数据?在高峰时间,我们所说的每分钟大约80-100k行到达OLTP侧,非高峰时间将显著下降到15-20k。最频繁更新的行每行约64字节,但有各种表等,因此数据非常多样化,每行最多可更新4000字节。OLTP是活动的24x5.5

最佳解决方案?

从我能拼凑出的最实际的解决方案如下:

  • 创建一个触发器,将所有DML活动写入旋转CSV日志文件
  • 执行所需的任何转换
  • 使用本机DW数据泵工具有效地将转换后的CSV泵入DW
为什么采用这种方法?

  • 触发器允许选择性表成为目标,而不是系统范围的+输出是可配置的(即进入CSV),并且相对容易编写和部署。SLONY使用类似的方法,开销是可以接受的
  • CSV易于快速转换
  • 易于将CSV泵入DW
考虑的备选方案……

  • 使用本机日志()。问题是,相对于我所需要的内容,它看起来非常冗长,而且解析和转换起来有点棘手。不过,它可能会更快,因为我认为与触发器相比,开销更小。当然,这会使管理变得更容易,因为它是系统范围的,但我不需要一些表(有些表用于持久存储JMS消息,我不想记录这些消息)
  • 通过Talend等ETL工具直接查询数据,并将其泵入DW。。。问题是OLTP模式需要调整以支持这一点,这有许多负面的副作用
  • 使用经过调整/黑客攻击的SLONY-SLONY在记录更改并将更改迁移到从属服务器方面做得很好,因此概念框架就在那里,但建议的解决方案似乎更简单、更干净
  • 使用墙

以前有人这样做过吗?想分享您的想法吗?

假设您感兴趣的表有(或可以增加)一个唯一的、索引的、顺序键,那么您只需发出
SELECT。。。从表中。。。WHERE key>:last_max_key
输出到文件,其中,
last_max_key
是最后一次提取的最后一个键值(如果是第一次提取,则为0)。这种增量、解耦方法避免了在插入数据路径中引入触发延迟(无论是自定义触发器还是修改的Slony),根据您的设置,可以更好地扩展CPU数量等。(但是,如果您还必须跟踪
UPDATE
s
,并且顺序键是由您添加的,那么您的
UPDATE
语句应该
键列设置为
NULL
,以便它获得一个新值并在下次提取时拾取。您将无法跟踪
删除
s这就是你提到泰伦德时的想法吗

除非您无法实现上述解决方案,否则我将不使用日志记录功能;日志记录很可能涉及锁定开销,以确保日志行按顺序写入,并且在多个后端写入日志时不会相互重叠/覆盖(检查Postgres源)锁定开销可能不是灾难性的,但如果可以使用增量
SELECT
选项,则可以不使用它。此外,语句日志记录将淹没任何有用的警告或错误消息,解析本身不会是瞬时的


除非您愿意解析WAL(包括事务状态跟踪,并准备在每次升级Postgres时重写代码)我也不一定会使用WAL——也就是说,除非您有可用的额外硬件,在这种情况下,您可以将WAL运送到另一台机器进行提取(在第二台计算机上,您可以无耻地使用触发器——甚至使用语句日志记录——因为无论发生什么,都不会影响主计算机上的
插入
/
更新
/
删除
性能。)请注意(在主计算机上),除非您可以将日志写入SAN,否则您将获得相当的性能损失(主要是在破坏文件系统缓存方面)从运行增量
选择到将WAL发送到不同的机器如果您能想到一个只包含id和“校验和”的“校验和表”,您不仅可以快速选择新记录,还可以快速选择更改和删除的记录


校验和可以是您喜欢的crc32校验和函数。

PostgreSQL中的new ON CONFLICT子句改变了我执行许多更新的方式。我提取新数据(基于行更新时间戳)在一个临时表中,然后在一条SQL语句中插入到目标表中,并进行ON CONFLICT UPDATE。如果目标表已分区,则需要跳过几个环(即直接命中分区表)。ETL可能在加载临时表时发生(最有可能发生),也可能在ON CONFLICT SQL中发生(如果不重要)。与其他“UPSERT”系统(更新、插入零行等)这显示了巨大的速度提升。在我们特定的DW环境中,我们不需要/不想容纳删除。查看冲突文档