对H2以及其他内存数据库大师的挑战

时间:2013-09-14 20:21:06

标签: java h2 in-memory-database jooq

我有一个有趣的场景,我相信,它是一个出色的IMDB应用程序(例如H2),可能还有jOOQ。但是,会出现一些有趣的挑战和问题。

我们开发了一个专门的,基于Java的ETL平台,用于保险数据转换,现已进入第四代。在不进行不必要的细节的情况下,我们会定期从SQL Server,DB2等源系统中提取数据,这些数据会在不同程度上进行标准化。保险数据转换有两个非常相关的特征:

  1. 我们通常一次转换一个保险实体(即政策,申请,索赔等)(除非它是包裹或其他交易分组的一部分,在这种情况下,我们可能会转换一些实体)时间)。因此,重要的是,给定的转换事务一次很少涉及甚至1Mb的数据。实际上,通过任何现代措施,典型的交易涉及的数据不到50K。

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

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

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

    2. 针对IMDB执行所有复杂的转换查询。同样,jOOQ可能会带来很大的好处。

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

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

      但是,我有两个问题:

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

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

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

      2. 目标加载 - 本讨论主要关注源端数据库处理,因为我们经常在目标端生成XML(为此我们有成熟的子系统)。但是,有时我们还需要直接处理目标端的数据库。在这种情况下,我们必须能够根据转换的数据直接插入/更新主流关系数据库。

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

        无论如何,目标加载的一般方法是否合理?
      3. 我为这篇文章的篇幅道歉,但这对我们的团队来说是一个至关重要的问题。非常感谢您提前回复。

1 个答案:

答案 0 :(得分:1)

有点偏离主题......要记住的一点是,H2是非分布式数据库,因此最好是一个相当原始的解决方案。从本质上讲,这是一个适用于单个JVM数据库的堆栈。除非你在谈论绝对简单的用例(我不认为你是这样),否则有更好的方法。

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

这里只差2美分。