Cassandra:如何建模传感器数据的时间序列?

时间:2016-05-30 10:53:43

标签: database-design cassandra cql

我需要在cassandra中存储传感器读数(版本2!)。 有n个传感器,每个传感器可以发送多达m种不同的值,这些值具有不同的类型(例如Float,Bool,String)。值必须存储在cassandra中。之后,将主要按时间范围查询值。所以查询可以“给我2016-05-01 09:00到2016-05-15 13:00的所有读数”。传感器ID /类型可能有过滤器,但主查询始终是时间。 (因此查询可能是“从2016-05-05给我传感器1和5的所有数据”,但很可能不是“给我传感器1和5的所有数据”。)

对于更详细的查询,如果必须扫描所有数据(受时间和可能的传感器ID限制),则可以。因此,对于查询“从2016-05-05给出传感器5的所有传感器数据,其中读数的浮点值大于1000”,如果cassandra必须从2016-05-05扫描传感器5的所有值,那就没关系!

我阅读了很多关于数据建模的博文/问题,(例如[1] [2] [3] [4] [5] [6])但是有些东西已经好几年了,我不确定,如果它仍然是正确的方法。

我的主要问题是:

  • 我使用什么数据类型作为时间戳(需要毫秒分辨率)
  • 如何定义密钥? (例如,我是否需要像每个例子一样使用小时主键?如果是,我可以在cassandra中将结果合并超过一小时,还是需要手动执行?)
  • 如何添加sensorID以便有效查询

传感器数据将始终按顺序插入,因此不会更改先前的数据,也不会添加时间戳低于当前最大值的数据。

1 个答案:

答案 0 :(得分:3)

  

我使用什么数据类型作为时间戳(需要毫秒分辨率)

timeuuid肯定是

  

如何定义密钥? (例如,我是否需要使用小时主键,如某些示例所用?如果是,我可以在cassandra中将结果合并超过一小时,还是需要手动执行?)

使用Cassandra进行数据建模的最大秘密是将物理分区的大小限制在可管理的范围内(约100Mb / 10百万个单元)

在您的情况下,每个传感器的子分区取决于插入率

如果某些传感器将数据插入数千个数据点/秒的疯狂数据,则每小时一个分区是合适的粒度。当然,每小时1个分区(PRIMARY KEY ((sensor_id, hour), insertion_time_in_timeuuid))将限制您的查询功能,例如如果您想在下午4点到晚上10点之间使用某些传感器的数据,则需要发出6个查询或使用IN子句(SELECT * FROM ... WHERE sensor_id=xxx AND hour IN (16, 17, 18, 19, 20, 21, 22)

如果插入率适中,您可以按天/周/月进行子分区。这里没有规则的拇指,因为它全部取决于数据量。

要记住的关键是要保持查询的简易性与分区大小之间的平衡。

  

如何添加sensorID以便也可以有效地查询

将它作为分区键的一个组成部分与子分区时间范围一起放置,例如: PRIMARY KEY( (sensor_id, hour), insertion_time_in_timeuuid)

  

传感器数据将始终按顺序插入,因此不会更改先前的数据,也不会添加时间戳低于当前最大值的数据。

CREATE TABLE sensor_data (
  sensor_id timeuuid,
  partitioning_time_range bigint,
  insertion_time_in_timeuuid timeuuid,
  float_value float
  int_value int,
  bool_value bool,
  text_value text,
  PRIMARY KEY( (sensor_id, hour), insertion_time_in_timeuuid)
) WITH CLUSTERING ORDER BY (insertion_time_in_timeuuid DESC);

要适应不同类型的数据,只需为数据类型(float_valuebool_value,...)创建一列。在运行时,如果你只使用4/5中的1列,Cassandra只会在磁盘上插入1个物理单元(与保留未使用列的空间的关系数据库不同)