Java 设计数据库(由hibernate访问)的策略,该数据库将包含大量的归档数据

Java 设计数据库(由hibernate访问)的策略,该数据库将包含大量的归档数据,java,hibernate,database-design,spring,Java,Hibernate,Database Design,Spring,我正在开发一个应用程序,它将集成数千个传感器,每15分钟发送一次信息。假设所有传感器的数据格式都相同。存储这些数据的最佳策略是什么?这样,每件事情都可以存档(可以访问),并且不会因为数据的大量增长而产生负面影响 我想这个问题与一般的数据库设计有关,但我想提到的是,我使用的是Hibernate(带有SpringRoo),所以可能已经有一些东西解决了这个问题 编辑:传感器是哑的,并且是现成的。不可能扩展它们。在网络中断的情况下,所有信息都将丢失。由于传感器在GPRS上工作,这种情况将是不太可能的(因

我正在开发一个应用程序,它将集成数千个传感器,每15分钟发送一次信息。假设所有传感器的数据格式都相同。存储这些数据的最佳策略是什么?这样,每件事情都可以存档(可以访问),并且不会因为数据的大量增长而产生负面影响

我想这个问题与一般的数据库设计有关,但我想提到的是,我使用的是Hibernate(带有SpringRoo),所以可能已经有一些东西解决了这个问题

编辑:传感器是哑的,并且是现成的。不可能扩展它们。在网络中断的情况下,所有信息都将丢失。由于传感器在GPRS上工作,这种情况将是不太可能的(因为GPRS提供商在瑞典是一个相当好的提供商,但它可以下降,人们对此无能为力)


排队机制是最重要的考虑因素,spring roo提供了易于使用的基于ACTIVEMQ的原型代码。

假设每15分钟有10000个传感器发送信息。为了在数据库端获得更好的性能,您可能必须按日期/时间、传感器类型或类别或其他因素对数据库进行分区。这还取决于您将如何查询数据

另一个瓶颈是Java/JavaEE应用程序本身。这取决于你的业务,比如,所有150000个传感器会同时发送信息吗?以及java应用程序将遵循的体系结构。您必须阅读关于高可伸缩性和性能的文章

以下是我对Java/Java EE解决方案的建议。

使用接收数据的应用程序集群,而不是单个应用程序

拥有一个控制器应用程序,控制哪个传感器将数据发送到群集中哪个应用程序实例之间的链接。应用程序实例可以从传感器提取数据,或者传感器可以将数据推送到应用程序实例,但控制器将控制哪个应用程序实例链接到哪组传感器。此控制器必须是动态的,以便可以添加、删除或更新传感器,并且应用程序实例可以随时加入或离开集群。确保控制器具有某种故障转移功能

所以,如果集群中有10000个传感器和10个应用程序实例,那么在任何给定时间都有1000个传感器链接到一个应用程序。如果您仍然想要更好的性能,那么您可以在集群中拥有20个应用程序实例,并且将有500个传感器链接到一个应用程序实例

应用程序实例可以托管在同一台或多台机器上,以便实现垂直和水平可伸缩性。每个应用程序实例都将是多线程的,并且具有本地持久性。这将避免主数据库服务器的瓶颈,并减少事务响应时间。这种本地持久性可以是SAN文件或本地RDBMS(如Java DB),甚至可以是MQ。若在数据库中本地持久化,那个么可以使用Hibernate进行同样的操作

将数据从本地持久性异步移动到主数据库。这取决于您如何在本地持久化数据。 若您使用基于文件的持久性,那个么您需要一个单独的线程来从文件中读取数据并插入主数据库存储库。 如果您使用本地数据库,那么该线程可以使用Hibernate在本地读取数据并将其插入主数据库存储库。 若您使用MQ,则可以使用线程或单独的应用程序将数据从队列移动到主数据库存储库

此解决方案的缺点是,报告某些数据的传感器与出现在主数据库中的数据之间会有一些延迟。


此解决方案的优势在于,它将为您提供高性能、可扩展性和故障转移。

这意味着您将获得大约1条记录/秒乘以您拥有的传感器数量,或者大约250万行/月乘以您拥有的传感器数量

Postgres具有继承和分区功能。这将使以下表格变得切实可行:

  • 传感器数据输出电流
  • 传感器数据\u 2010\u 01
  • 传感器数据_2009_12
  • 传感器数据\u 2009\u 11
  • 传感器数据\u 2009\u 10
每个表包含一个月的测量值。然后,可以创建由这些子表“组成”的父表sensordata,这意味着对sensordata的查询将自动遍历子表,但只有规划人员推断的表才能包含该查询的数据。因此,如果您说将数据按月份(这是一个日期范围)进行分区,并在每个子表上使用日期约束表示该愿望,然后按日期范围进行查询,然后,计划器(基于子表约束)将能够从查询的执行中排除那些不包含满足日期范围的行的子表

当一个月结束时(比如2010年1月刚刚转变为2010年2月),您可以将sensordata_current重命名为刚刚结束的月份(2010_01),创建一个新的sensordata_current,将2010_01中的任何行移到新创建的sensordata_current中,该行的时间戳为2月,最后,在2010年1月添加一个约束,表示它只有2010年1月的数据。同时在2010年1月删除不必要的指数。在Postgres中,这一切都可以通过将其封装到事务中来实现原子化

或者,您可能需要不使用_current,而是创建一个新的2010年_01,并将所有1月份的行从_current移到其中(然后可以选择抽真空_current以立即回收空间-尽管如果您的行是consant大小,那么对于最新的Postgres版本,这样做没有多大意义)。在此cas中,您的移动(选择进入/删除)将花费更长的时间