我可以选择哪些选项来存储和查询大量重复的数据?

Nic*_*las 4 java database compression hibernate jdbc

我正在评估 Java 中高效数据存储的选项。该数据集是带有命名主键的带时间戳的数据值。例如

Name: A|B|C:D
Value: 124
TimeStamp: 01/06/2009 08:24:39,223
Run Code Online (Sandbox Code Playgroud)

可能是给定时间点的股票价格,所以我认为这是一个经典的时间序列数据模式。然而,我确实需要一个通用的 RDBMS 解决方案,它可以与任何合理的 JDBC 兼容数据库一起使用,因为我想使用 Hibernate。因此,像 Oracle 这样的数据库的时间序列扩展并不是真正的选择,因为我希望实现者能够使用他们自己的支持 JDBC/Hibernate 的数据库。

这里的挑战就是短时间内积累的大量数据。到目前为止,我的实现主要围绕定义定期汇总和清除计划,其中原始数据被聚合到“日”、“周”、“月”等表中,但缺点是粒度的早期损失以及存储在不同数据中的周期之间的周期不匹配带来的轻微不便。聚合体。

这一挑战的选择有限,因为在保留数据原始粒度的同时可以物理压缩多少数据存在绝对限制,并且使用关系数据库和支持通用 JDBC 的指令加剧了这一限制。 。

借用经典数据压缩算法中的概念概念,并利用同一命名键的许多连续值可以相同的事实,我想知道是否有方法可以通过将重复值合并为无缝地减少存储记录的数量一个逻辑行,同时还存储一个计数器,该计数器有效地指示“接下来的n 条记录具有相同的值”。这个实现看起来很简单,但代价是,使用标准 SQL 进行查询时,数据模型现在异常复杂,尤其是在使用任何类型的聚合 SQL 函数时。这显着降低了数据存储的实用性,因为只有复杂的自定义代码才能将数据恢复到“解压缩”状态,从而导致数百种工具的阻抗不匹配,而这些工具将无法正确呈现此数据。

我考虑了定义自定义 Hibernate 类型的可能性,这些类型基本上“理解”压缩数据集并将其备份并使用动态创建的合成行返回查询结果。(除了严格控制的输入流之外,数据库将对所有客户端只读)。除了原始 JDBC 之外,我想到的几个工具还将与 Hibernate/POJOS 集成(例如 JasperReports),但这并不能真正解决聚合函数问题,并且可能还有许多其他问题。

因此,我正在部分地接受自己可能必须使用更专有的[可能非 SQL] 数据存储(任何建议都表示赞赏),然后专注于编写伪 JDBC 驱动程序的可能不太复杂的任务,以至少简化与外部工具。

我听说过一种称为“位打包文件”的东西作为实现这种数据压缩的机制,但我不知道有任何数据库可以提供此功能以及我想做的最后一件事(或者可以做,真的...... )是写我自己的数据库。

有什么建议或见解吗?

cle*_*tus 5

Hibernate(或任何 JPA 解决方案)不适合这项工作。

JPA/Hibernate 不是一个轻量级的解决方案。在大容量应用中,开销不仅很大而且令人望而却步。您确实需要研究网格和集群解决方案。这里不再重复各种技术的概述。

我在金融市场信息系统方面拥有丰富的经验。你说的一些话让我印象深刻:

  • 你有大量的原始数据;
  • 您想要对该数据应用各种聚合(例如开盘价/最高价/最低价/收盘价每日摘要);
  • 高可用性可能是一个问题(在这类系统中总是如此);和
  • 低延迟可能是一个问题(同上)。

现在,对于网格/集群类型的解决方案,我将它们松散地分为两类:

  1. 基于地图的解决方案,例如 Coherence 或 Terracotta;和
  2. 基于 Javaspaces 的解决方案,例如 GigaSpaces。

我经常使用 Coherence,Map 解决方案可能很好,但也可能有问题。相干图可以有监听器,您可以使用这种东西来执行以下操作:

  • 市场价格警报(用户可能希望在价格达到一定水平时收到通知);
  • 衍生品定价(例如,当基础证券改变最后交易价格时,交易所交易的期权定价系统将需要重新定价);
  • 出于对账目的,交易匹配/预订系统可能需要匹配收到的交易通知;
  • ETC。

所有这些都可以通过侦听器来完成,但在 Coherence 中,侦听器必须很便宜,这会导致诸如 Map 拥有侦听器而不是向另一个 Map 写入内容之类的情况,并且这可能会持续一段时间。此外,修改缓存条目可能会出现问题(尽管也有处理此类问题的机制;我说的是关闭市场价格警报之类的情况,这样它就不会再次触发)。

我发现 GigaSpaces 类型的网格解决方案对于此类应用程序更具吸引力。读取(或破坏性读取)操作是一种高度优雅且可扩展的解决方案,您可以获得亚毫秒性能的事务性网格更新。

考虑两种经典的队列架构:

  • 请求/响应:错误的消息可能会阻塞队列,虽然可以有多个发送者和接收者(为了可扩展性),但扩大管道数量并不总是那么简单;和
  • 发布/订阅:这将发送者和接收者解耦,但缺乏可扩展性,因为如果您有多个订阅者,他们每个人都会收到消息(不一定是您想要的预订系统)。

在 GigaSpaces 中,破坏性读取就像可扩展的发布-订阅系统,而读取操作就像传统的发布-订阅模型。有一个构建在网格之上的 Map 和 JMS 实现,它可以进行 FIFO 排序。

现在我听到你问坚持怎么样?坚持是决定所有其他事情的结果。对于这种类型的应用程序,我喜欢持久化即服务模型(讽刺的是,这是关于 Hibernate 的,但它适用于任何事物)。

基本上,这意味着您的日期存储点击是异步的,并且它可以很好地处理汇总数据。就像您可以让服务监听交易通知并仅保留它感兴趣的通知(如果需要,则在内存中聚合)。您可以通过这种方式计算开盘价/最高价/最低价/收盘价。

对于大量数据,您并不希望将其全部写入数据库。反正不是同步的。持久存储加上数据仓库可能更适合您,但这又取决于需求、数量等。

这是一个复杂的话题,我只是真正接触过它。希望对您有帮助。