3

我有一个有趣的场景,我相信这是 IMDB(例如H2)和可能的jOOQ的出色应用。然而,出现了一些有趣的挑战和问题。

我们开发了一个专门的、基于 Java 的 ETL 平台,用于保险数据转换,现在已经是第四代了。在不涉及不必要的细节的情况下,我们例行地从 SQL Server、DB2 等源系统中提取数据,这些数据经过了不同程度的规范化。保险数据转换有两个与此处高度相关的特征:

  1. 我们通常一次转换一个保险实体(即保单、申请、索赔等)(除非它是包或其他交易分组的一部分,在这种情况下,我们可能一次转换几个实体)。因此,重要的是,给定的转换交易一次很少涉及 1 Mb 的数据。事实上,一个典型的交易涉及不到 50K 的数据——以任何现代衡量标准来说都是微不足道的。

  2. 由于源系统和目标系统在模式、粒度甚至底层语义上的差异如此之大,因此转换可能非常复杂。在源处理方面,查询繁多且复杂,经常连接很多表,使用子查询等。鉴于此,获得合理的性能意味着以某种方式保存查询结果。到目前为止,我们一直依赖一种涉及“保险地图”的专有方法,这是一种专门的 Java 地图。我们知道这种方法最终是不够的,但它最初满足了我们的需求。

现在我有一些时间来反思,我正在考虑一个长期的方法。如果我们只考虑上面的基本特征,那么像 H2 这样的 IMDB 似乎是完美的:

  1. 预先针对源数据库(例如 SQL Server)执行所有复杂查询,创建表,执行插入/更新,以便创建与单个转换事务(例如单个保险单)有关的所有数据的 IMDB 表示)。顺便说一句,我可以看到 jOOQ 在这里(和其他地方)对简化和提高这些查询的类型安全性有多大帮助。

  2. 针对 IMDB 执行所有复杂的转换查询。同样,jOOQ 可能有显着的好处。

  3. 为每个保险转换交易丢弃并重新创建 IMDB。

我喜欢这种方法(至少在 H2 中)的一件事是能够将查询封装在基于 Java 的存储过程中——比编写 T-SQL 存储过程要好得多。并且它会再次使事情变得更容易/更安全使用 jOOQ 对付 IMDB,而不是,例如,本机 H2 存储的 proc API?

但是,我有两个担忧:

  1. 序列化——这实际上是一个分布式平台(出于讨论目的,我在上面简化了我的描述),我们相当大量地使用服务和消息队列来传递/排队数据。当我们使用 XML 数据源时,这一切都非常有效,这种情况经常发生。这对 IMDB 的效果如何?

    对于给定的保险交易 IMDB,我们必须能够 a) 序列化 IMDB,b) 传输和/或排队 IMDB,最后,c) 将数据反序列化回功能齐全的 IMDB 以进行转换处理。

    例如,使用 H2 执行此操作的最佳方法似乎是使用 SQL SCRIPT 命令序列化数据,然后运行脚本来反序列化数据。我想知道这种方法的性能特征。我不认为我们的平台对性能特别敏感,但我确实想避免一种特别缓慢或架构上笨拙的方法。

  2. 目标加载——本次讨论集中在源端数据库处理,因为我们经常在目标端生成 XML(为此我们有成熟的子系统)。然而,有时我们也需要直接寻址目标端的数据库。在这种情况下,我们必须能够根据转换后的数据直接对主流关系数据库进行插入/更新。

    我正在考虑的方法再次使用 IMDB,但在目标端。转换后的数据使用与实际目标数据库相同的模式填充 IMDB。然后,可以根据需要对这个目标 IMDB 进行序列化和传输。最后,目标 IMDB 的内容将用于插入/更新实际的目标数据库(当然,它可能有许多 GB 的数据)。如果我可以对 IMDB 使用一个简单的 SQL SCRIPT 语句来生成一个包含 INSERT/UPDATE 语句的脚本,那么我可以简单地针对目标数据库运行该脚本,这将是巨大的(但我并不乐观)。我怀疑这不会那么容易。

    无论如何,这种一般的目标加载方法是否合理?

对于这篇文章的篇幅,我深表歉意,但这对我们的团队来说是一个至关重要的问题。非常感谢您的回复。

4

1 回答 1

1

有点跑题了……要记住的一件事是,H2 是非分布式数据库,因此充其量是一个相当原始的解决方案。从本质上讲,这是一个适用于单个 JVM 堆的数据库。除非您谈论的是绝对简单的用例(我认为您不是),否则有更好的方法。

例如,GridGain 的内存数据库在内部使用 H2 进行 SQL 处理(具有所有优点),但也提供 SQL 的完整分发以及许多其他功能。还有其他分布式内存数据库,甚至一些复杂的数据网格可以适合您的用例。

这里只有我的 2 美分。

于 2013-09-15T20:39:04.110 回答