14

背景:

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

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

多少数据?在高峰期,我们谈论每分钟大约 80-100k 行到达 OLTP 端,非高峰期这将显着下降到 15-20k。最频繁更新的行每行约为 64 字节,但有各种表等,因此数据非常多样化,每行最多可达 4000 字节。OLTP 24x5.5 处于活动状态。

最佳解决方案?

据我所知,最实用的解决方案如下:

  • 创建 TRIGGER 以将所有 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

有没有人这样做过?想分享你的想法吗?

4

3 回答 3

11

SELECT ... FROM table ... WHERE key > :last_max_key假设您感兴趣的表具有(或可以增加)一个唯一的、索引的、顺序键,那么您将通过简单地将输出发布到文件中获得更好的价值,其中last_max_key最后一个键值来自上次提取(如果是第一次提取,则为 0。)这种增量、解耦的方法避免在插入数据路径中引入触发延迟(无论是自定义触发器还是修改后的 Slony),并且根据您的设置可以更好地扩展 CPU 数量等。(但是,如果您还必须跟踪UPDATEs,并且顺序键是由您添加的,那么您的UPDATE语句应该SET是键列,NULL以便它获得一个新值并被下一次提取选中。你会没有触发器就无法跟踪DELETEs。)这就是您在提到 Talend 时的想法吗?

除非您无法实施上述解决方案,否则我不会使用日志记录工具;日志记录很可能涉及锁定开销,以确保日志行是按顺序写入的,并且当多个后端写入日志时不会相互重叠/覆盖(检查 Postgres 源。)锁定开销可能不是灾难性的,但如果没有它,你可以这样做您可以使用增量SELECT替代方案。此外,语句记录会淹没任何有用的 WARNING 或 ERROR 消息,并且解析本身不会是即时的。

除非您愿意解析 WAL(包括事务状态跟踪,并准备好在每次升级 Postgres 时重写代码),否则我也不一定会使用 WAL——也就是说,除非您有额外的硬件可用,在这种情况下您可以将 WAL 发送到另一台机器进行提取(在第二台机器上,您可以无耻地使用触发器——甚至是语句日志记录——因为那里发生的任何事情都不会影响INSERT/ UPDATE/DELETE主要机器上的性能。)请注意,性能方面(在主要机器上),除非您可以将日志写入 SAN,否则您会从运输 WAL 中获得相当的性能损失(主要是在文件系统缓存方面)从运行增量到不同的机器SELECT

于 2010-03-30T05:27:56.917 回答
3

如果您能想到一个仅包含 id 和“校验和”的“校验和表”,您不仅可以快速选择新记录,还可以快速选择更改和删除的记录。

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

于 2010-04-17T21:17:51.827 回答
0

PostgreSQL 中新的 ON CONFLICT 子句改变了我进行许多更新的方式。我将新数据(基于 row_update_timestamp)拉到一个临时表中,然后在一个 SQL 语句中使用 ON CONFLICT UPDATE 将其插入到目标表中。如果您的目标表是分区的,那么您需要跳过几圈(即直接命中分区表)。ETL 可能在您加载 Temp 表(最有可能)或 ON CONFLICT SQL(如果微不足道)时发生。与其他“UPSERT”系统(更新、零行时插入等)相比,这显示了巨大的速度提升。在我们特定的 DW 环境中,我们不需要/不想容纳 DELETE。查看 ON CONFLICT 文档 - 它让 Oracle 的 MERGE 物有所值!

于 2017-01-03T16:37:17.943 回答