我对Cassandra还是陌生的,我正在尝试了解如何为物联网传感器设计表格。
这个想法是拥有多个设备,每个设备上都连接有多个传感器,这些设备定期发送数据(每个传感器每天每个设备最多约200000个值)
我希望能够或多或少实时地查询传感器的最新值,以获取特定的传感器和设备列表。此外,设备并非总是发送数据,并且可能会长时间关闭。
大量阅读后,我想到了类似的东西
CREATE TABLE "sensor_data" (
deviceid TEXT,
sensorid TEXT,
ts timestamp,
value TEXT,
PRIMARY KEY ((deviceid, sensorid), ts)
) WITH CLUSTERING ORDER BY (ts DESC);
其背后的想法是对每个设备和传感器(例如
)执行一次查询Select deviceid, sensorid, ts, value where deviceid = "device1" and sensorid = "temperature" limit 1
并为每个设备和传感器运行此程序。不是全部返回一个查询(这是理想的选择),但似乎足够快,可以为几个设备运行多达100个左右的传感器(可能并行化查询)。
但是,到目前为止,我了解到这会给我的行增加很多列,并且在长期存储和Cassandra限制方面可能会很复杂。
我认为也许在表中添加诸如日期之类的内容(如在某些博客和指南中看到的那样)可能是个好主意
CREATE TABLE "sensor_data" (
deviceid TEXT,
sensorid TEXT,
date TEXT
ts timestamp,
value TEXT,
PRIMARY KEY ((deviceid, sensorid, date), ts)
) WITH CLUSTERING ORDER BY (ts DESC);
然后像这样查询
Select deviceid, sensorid, date, ts, value where deviceid = "device1" and sensorid = "temperature" and date = "2018-11-14" limit 1
那还有意义吗?感觉这可能会减轻存储问题并允许将来更轻松地归档旧数据,但是如果该设备停机一天或更长时间,我该如何查询特定传感器和设备的最新值?我是否真的需要查询1天,如果什么都没找到,请查询前一天,依此类推(也许将其限制在最近几天左右)?
在Cassandra中是否有更好的方法来解决这个问题?或者我的方向正确吗?
答案 0 :(得分:3)
您会遇到的部分问题是,每个传感器每天都会有20万个读数。通常,您希望将每个分区都保留在100k rows下。因此,您的第二个想法(将日期作为PK的一部分)可能存在性能问题。
您真正想要做的就是我们所说的“存储桶”;如何将事物组合在一起,以便查询可用和高效。
要真正帮助您解决此问题,我们需要了解更多信息:
根据您的答案将其结合到答案中(如下):
好的,这是一个潜在的主意...
我们确实关心转储,但是试图将其保留在分区中的100k /分区最佳行附近。
您将需要两个表:
查找表如下所示:
CREATE TABLE lookup-table (
deviceid TEXT,
sensor-map MAP,
PRIMARY KEY (deviceid)
);
deviceid
是每个设备的唯一ID sensor-map
是给定设备具有的传感器的JSON map以及该特定传感器的相应唯一ID(例如,{温度:183439,湿度:84543292,其他传感器:blah}) SELECT * FROM lookup-table WHERE deviceid = 1234;
传感器表如下所示:
CREATE TABLE sensor_data (
sensorid TEXT,
sensor_value (whatever data type fits what you need),
ts TIMESTAMP,
reading_date date,
time_bucket int,
PRIMARY KEY ((reading_date, sensorid, time_bucket), ts)
) WITH CLUSTERING ORDER BY (ts DESC);
reading_date
),并每天分成两部分(由于您期望的读数量大);上午或下午; AM等于存储区1,PM等于存储区2。或使用24小时制,其中0-1200等于1,1300-2399等于2 sensorid
和
time_bucket
来自您实际要求的时间
查询(例如,如果时间为1135小时,则time_bucket = 1
)和reading_date
来自您查询的实际日期ts DESC
进行聚类,因此它将检索
给定sensorid
的最新读数。所以看起来像
SELECT * from sensor_data WHERE reading_date = 12/31/2017 AND sensorid = 1234 AND time_bucket = 1 LIMIT 1;
ts
保留为聚类列,您将能够保留给定传感器的所有读数;没有一个会被覆盖重要信息:如果在一天24小时内传感器读数均匀分布,则此方法非常有用。但是,如果您上午阅读大量信息,而下午根本没有阅读,那么这不是一个平衡点,我们必须找出另一种存储方式。但是,我认为您可以了解正在发生的事情。
要查询:
sensorid
;拥有这些sensorid
之后,就可以将其用于下一步了sensor_value
的每个sensorid
将有 n 个查询time_bucket
),因此您应该在所有分区中均匀分布 最后:按给定的值给我最新的sensorid
为此,有几种不同的方法...
对于其他C *表:
CREATE TABLE sensor_by_value (
sensor-value INT,
ts TIMESTAMP,
sensorid TEXT,
reading_date DATE,
time_bucket INT,
PRIMARY KEY ((sensor-value, reading_date), ts)
) WITH CLUSTERING ORDER BY (ts DESC);
您肯定需要在这里花一些时间:
最终提示
研究压缩策略:特别是time window compaction strategy(TWCS)并添加default_time_to_live
您的数据在初次插入后似乎是不变的
TWCS将使压缩的操作开销大大降低,因为您可以在所需的时间范围内对其进行微调
default_ttl
也将帮助您在不再需要数据时删除数据。
这个答案和/或满足您要回答的查询吗?如果没有,请告诉我们,我们可以进行迭代。
要了解所有这些内容,请访问DataStax Academy进行大量的免费培训。数据建模(DS 220)是一门很棒的课程!