1

我通过说明来警告这个问题:我对 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)进行查询操作,我有什么选择?查询通常包括对数据的计数(例如,计数传感器 A 在日期 B 的读数,其中 some_ugc_valueX = C 和 some_ugc_valueY = D)。值得注意的是,将有比通常一次查询更多的数据点。一个读数可能有 20 个数据值,但可能只有 2 个或 3 个会被查询 - 只是提前不知道哪个。

目前我想到了:

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

也许我会以错误的方式解决这个问题?也许 Cassandra 甚至不是此类数据的最佳选择?

4

1 回答 1

0

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

基于来自用户生成内容的数据的查询将变得很复杂——您将无法生成一个万能的表定义,从而允许对基于 UGC 内容的查询进行快速响应。即使您选择使用 Maps,Cassandra 也必须在每个查询中反序列化整个数据结构,因此对于大型 Maps 来说,这并不是一个真正的选择——正如您在问题中所建议的那样,情况可能就是这样。

另一种方法可能是以序列化形式存储传感器数据,例如 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 和 sensor 查询:

>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]。)

于 2013-11-06T17:44:16.313 回答