未知数据的Cassandra时间切片数据模型
我警告这个问题:我对NoSQL有点陌生,对Cassandra也很陌生,但它似乎很适合我要做的事情 假设我有一个以合理间隔提供输入的传感器列表。我建议的数据模型是根据传感器的名称、位置(区域)和日期(写为yyyyMMdd)进行分区,并根据实际发生读数的时间对当天的读数进行聚类。我们的想法是,“在日期B获取传感器A的所有读数”的查询应该非常快。到目前为止,我认为还不错。表/CF在CQL中如下所示:未知数据的Cassandra时间切片数据模型,cassandra,Cassandra,我警告这个问题:我对NoSQL有点陌生,对Cassandra也很陌生,但它似乎很适合我要做的事情 假设我有一个以合理间隔提供输入的传感器列表。我建议的数据模型是根据传感器的名称、位置(区域)和日期(写为yyyyMMdd)进行分区,并根据实际发生读数的时间对当天的读数进行聚类。我们的想法是,“在日期B获取传感器A的所有读数”的查询应该非常快。到目前为止,我认为还不错。表/CF在CQL中如下所示: CREATE TABLE data ( area_id int, sensor var
CREATE TABLE data (
area_id int,
sensor varchar,
date ascii,
event_time timeuuid,
PRIMARY KEY ((area_id, sensor, date), event_time)
) WITH CLUSTERING ORDER BY (event_time DESC);
然而,这实际上并不包括任何数据,我不知道如何将其添加到模型中。每次读取(来自同一个传感器)都可能有不同的任意数据集,我无法提前知道这是什么。例如,我可以得到温度数据,湿度数据,两者都可以,或者我可以得到我以前从未见过的东西。由实际记录数据的人决定他们想要提交什么(不是从自动传感器读取)
鉴于我想对这些数据(基本上是UGC)进行查询操作,我的选择是什么?查询通常包括对数据的计数(例如,在日期B上传感器A的计数读数,其中一些值X=C和一些值Y=D)。值得注意的是,将有比通常一次查询更多的数据点。一个读数可能有20个数据值,但可能只会查询2或3个数据值——只是不知道提前查询哪个数据值
目前我想到:
也许我走错了方向?也许卡桑德拉甚至不是这类数据的最佳选择;博士,你不能同时选择速度和绝对灵活性;-) 基于来自用户生成内容的数据的查询将非常复杂-您将无法生成一个一刀切的表定义,该表定义将允许快速响应基于UGC内容的查询。即使您选择使用Maps,Cassandra也必须对每个查询的整个数据结构进行反序列化,因此它实际上不是big Maps的选项,正如您在问题中所建议的那样 另一种方法是以串行形式存储传感器数据,例如json。这将为存储内容提供最大的灵活性,但代价是无法进行复杂的查询。序列化/反序列化负担推送到客户机,所有数据通过线路发送。下面是一个简单的例子: 表的创建(比您的示例稍微简单-我已经删除了
date
):
插入:
insert into data(area_id,sensor,event_time,data) VALUES (1,'sensor1',now(),'["datapoint1":"value1"]');
insert into data(area_id,sensor,event_time,data) VALUES (1,'sensor2',now(),'["datapoint1":"value1","count":"7"]');
按区域id和传感器查询:
>select area_id,sensor,dateof(event_time),data from data where area_id=1 and sensor='sensor1';
area_id | sensor | dateof(event_time) | data
---------+---------+--------------------------+-------------------------
1 | sensor1 | 2013-11-06 17:37:02+0000 | ["datapoint1":"value1"]
(1 rows)
按区域id查询:
> select area_id,sensor,dateof(event_time),data from data where area_id=1;
area_id | sensor | dateof(event_time) | data
---------+---------+--------------------------+-------------------------------------
1 | sensor1 | 2013-11-06 17:37:02+0000 | ["datapoint1":"value1"]
1 | sensor2 | 2013-11-06 17:40:49+0000 | ["datapoint1":"value1","count":"7"]
(2 rows)
(使用
[cqlsh 4.0.1 | Cassandra 2.0.1 | CQL spec 3.1.1 | Thrift protocol 19.37.0]进行测试)
)我猜这类似于使用映射字段,但允许客户端处理(反)序列化,它可能会做得稍微好一点。可能值得一提的是,我希望JSON数据点比任何查询中实际使用的数据点都多(我将更新问题以反映这一点)。这意味着在可能只需要1或2个字段(尽管不保证)的情况下,通过“在线”来反序列化完整的有效负载。如果一天有100万条记录,那就是很多数据。这可能是其他人正在做的——我不确定。我认为计数应该保持在一个单独的表中。如果你正在寻找最佳速度,你应该考虑每一个查询类型的一个表。我已经详细阐述了我的答案-你的点在满负荷是一个重要的考虑因素。您将在负载大小和灵活性之间进行权衡。如果您对传感器数据了解得更多,您可以为每种传感器类型编写自定义表,并对其进行更复杂的查询。不幸的是,在事先不知道结构的情况下,你将无法做到这一点。我想我将在这里使用混合解决方案。我将在与您描述的模式类似的模式中序列化完整事件。对于任何复杂的操作来说,将其取出并反序列化将是唯一的方法。我还将通过值对再次存储数据(嘿,存储是便宜的对),大致如下:创建表sensor_composite(area_id int,sensor varchar,date ascii,property varchar,event_time timeuuid,value varchar主键((area_id,sensor,date),property,event_time))。。。其目的是可以用于快速属性读取。是的,我认为这是有意义的-非规范化是新的规范化;-)
> select area_id,sensor,dateof(event_time),data from data where area_id=1;
area_id | sensor | dateof(event_time) | data
---------+---------+--------------------------+-------------------------------------
1 | sensor1 | 2013-11-06 17:37:02+0000 | ["datapoint1":"value1"]
1 | sensor2 | 2013-11-06 17:40:49+0000 | ["datapoint1":"value1","count":"7"]
(2 rows)