代码之家  ›  专栏  ›  技术社区  ›  Nicholas

在大量数据重复的情况下,我有什么选择来存储和查询大量数据?

  •  4
  • Nicholas  · 技术社区  · 17 年前

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

    Name: A|B|C:D
    Value: 124
    TimeStamp: 01/06/2009 08:24:39,223
    

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

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

    这一挑战的选择有限,因为在保持数据原始粒度的同时,物理压缩的数据量是绝对有限的,而使用关系数据库和通用JDBC数据库的指令加剧了这一限制。

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

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

    因此,我在一定程度上接受了自己可能不得不使用更专有的(可能是非SQL的)数据存储(任何建议都值得赞赏),然后专注于编写伪JDBC驱动程序这一可能不太复杂的任务,以至少简化与外部工具的集成。

    我听到有人提到一种叫做“ 位打包文件 “作为实现这种数据压缩的一种机制,但我不知道有任何数据库提供这种功能,我最不想做的事情(或者可以做的事情,真的……)就是编写自己的数据库。

    有什么建议或见解吗?

    5 回复  |  直到 17 年前
        1
  •  4
  •   Community Mohan Dere    9 年前

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

    JPA/Hibernate不是一个轻量级的解决方案。在高容量应用程序中,开销不仅很大,而且令人望而却步。你真的需要调查一下 grid and cluster solutions 。我不会在这里重复各种技术的概述。

    我在金融市场信息系统方面有很多经验。你说的几句话让我印象深刻:

    • 你有很多原始数据;
    • 您希望对该数据应用各种聚合(例如打开/高/低/关闭每日摘要);
    • 高可用性可能是一个问题(在这类系统中总是如此);和
    • 低延迟可能是一个问题(同上)。

    现在,对于网格/集群类型的解决方案,我将其大致分为两类:

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

    我经常使用Coherence,Map解决方案可能很好,但也可能有问题。一致性图上可以有监听器,你可以使用这种东西来做以下事情:

    • 市场价格警报(用户可能希望在价格达到一定水平时收到通知);
    • 衍生品定价(例如,当标的证券的最后交易价格发生变化时,交易所交易的期权定价系统将希望重新定价);
    • 交易匹配/预订系统可能希望匹配收到的交易通知以进行对账;
    • 等等

    所有这些都可以通过监听器来完成,但在连贯性中,例如监听器必须便宜,这导致像Map这样的东西有一个监听器,而不是向另一个Map写入内容,这可能会持续一段时间。此外,修改缓存条目可能会有问题(尽管也有处理此类问题的机制;我说的是关闭市场价格警报这样它就不会触发第二次)。

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

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

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

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

    现在,我听到你问什么是坚持不懈?坚持是决定所有其他事情的结果。对于这种应用程序,我喜欢 Persistence as a Service 模型(讽刺的是,它写的是Hibernate,但它适用于任何东西)。

    基本上,这意味着你的日期存储点击是异步的,它可以很好地处理摘要数据。就像你可以让一个服务监听交易通知,并只保留它感兴趣的通知(如果需要,可以在内存中聚合)。你可以这样做开盘/高/低/收盘价。

    对于大容量数据,您并不想将其全部写入数据库。无论如何都不是同步的。持久存储加上数据仓库可能更适合你,但这也取决于需求、数量等。

    这是一个复杂的话题,我只触及了它。希望这对你有所帮助。

        2
  •  2
  •   Javamann    17 年前

    你可能会发现听它很有趣 Michael Stonebraker's presentation at Money:Tech 他触及了您提到的许多需要,并说明了三大巨头(SQL Server、Oracle和DB2)将永远无法满足tick存储的需求(看起来您正在构建tick存储)。他在柱店之外挖掘,我同意这是正确的方向。他甚至讨论了压缩和速度,这对你来说都是问题。

    以下是一些你可能会感兴趣的链接:

        3
  •  2
  •   JD Long    17 年前

    我会看一个 column oriented database 。这对这种应用程序来说太好了

        4
  •  1
  •   Apocalisp    17 年前

    许多支持JDBC的数据库管理系统(如Oracle)在物理存储引擎中提供压缩。例如,Oracle有一个没有解压缩开销的“压缩”表的概念:

    http://www.ardentperf.com/wp-content/uploads/2007/07/advanced-compression-datasheet.pdf

        5
  •  0
  •   Nicholas    17 年前

    谢谢你的回答。

    Cletus,我很欣赏这个大纲,但我不能做出的权衡之一是放弃数据库的灵活性和与JDBC/Hibernate的兼容性,以允许使用所有可用的工具。此外,虽然我没有明确说明这一点,但我不想强迫我的用户采用(可能昂贵的)商业解决方案。如果他们有数据库品牌X,让他们使用它。如果他们不在乎,我们建议开源数据库品牌Y。基本上,该应用程序有多个面,其中一个是传入数据的存储库,但另一个面是报告源,我 真正地 不想从事编写报告生成器的工作。

    虽然我还没有真正对它进行负载测试,但我对它印象深刻 LucidDB 它是一个面向列的数据库,提供了良好的查询性能和看似良好的数据压缩。它有一个JDBC驱动程序,但据我所知,它还没有Hibernate方言。它还支持用户定义的转换,简而言之,我认为这将使我能够无缝地将重复和连续的值压缩到一个“行”中,但在查询时将它们吹回多个“合成”行,所有这些都是在查询调用者看不见的情况下完成的。最后,它支持外部表的这一漂亮特性,其他支持JDBC的数据库表可以在LucidDB中前置。我认为这对于为其他数据库提供一定程度的支持可能是无价的。

    谢谢你的指点,Javaman。它把我定位在LucidDB上。