未知数据的卡桑德拉时间切片数据模型



我警告这个问题:我对NoSQL有点陌生,对Cassandra也很陌生,但它似乎很适合我正在尝试做的事情。

假设我有一个传感器列表,以合理的间隔提供输入。我提出的数据模型是按传感器的名称、位置(区域)和日期(写为 yyyyMMdd)进行分区,并根据读数发生的实际时间对当天的读数进行聚类。想法是,对"从日期 B 的传感器 A 获取所有读数"的查询应该非常快。到目前为止,我认为一切顺利。表/CF 在 CQL 中如下所示:

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 的读数进行计数,其中 some_ugc_valueX = C 和 some_ugc_valueY = D)。值得注意的是,数据点将比通常一次查询的数据点多。一个读数可能有 20 个数据值,但可能只会查询 2 或 3 个 - 只是不知道提前哪个。

目前我想到了:

  1. 每个传感器读数的数据存储为映射类型。这肯定会使模型变得简单,但我的理解是查询会很困难吗?我想我需要为每个传感器读数拉回整个地图,然后检查值并将其计算在 Storm/Hadoop/whatever 中的 Cassandra 之外。
  2. 将每个用户值存储为另一列(具有 event_time uuid 的复合列)。这意味着不使用 CQL,因为它不支持在插入时添加任意新列。但是,Thrift API 确实允许这样做。这意味着我可以让卡桑德拉自己进行计数。

也许我这样做的方式不对?也许Cassandra甚至不是此类数据的最佳选择?

tl;dr. 你不能同时选择速度和绝对的灵活性;-)

基于用户生成内容数据的查询将非常复杂 - 您将无法生成一个一刀切的表定义,该定义将允许快速响应基于 UGC 内容的查询。即使您选择使用地图,Cassandra 也必须在每个查询中反序列化整个数据结构,因此它不是大地图的真正选择 - 正如您在问题中建议的那样,情况很可能如此。

另一种方法是以序列化形式存储传感器数据,例如 json。这将为存储的内容提供最大的灵活性 - 代价是无法进行复杂的查询。序列化/反序列化负担被推到客户端,所有数据都通过网络发送。下面是一个简单的示例:

表创建(比您的示例简单一些 - 我已经删除了date):

create table data(
  area_id int, 
  sensor varchar, 
  event_time timeuuid, 
  data varchar, 
  primary key(area_id,sensor,event_time)
);

插入:

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"]');

按area_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)

按area_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] 进行测试。

最新更新