时间序列数据的Cassandra分区键

时间:2016-03-16 23:06:24

标签: php cassandra cql cqlsh

我正在测试Cassandra作为时间序列数据库。

我创建数据模型如下:

CREATE KEYSPACE sm WITH replication = {
  'class': 'SimpleStrategy',
  'replication_factor': 1
};

USE sm;

CREATE TABLE newdata (timestamp timestamp,
  deviceid int, tagid int,
  decvalue decimal,
  alphavalue text,
  PRIMARY KEY (deviceid,tagid,timestamp));

在Primary键中,我将deviceid设置为分区键,这意味着具有相同设备ID的所有数据将写入一个节点(它是指一个机器还是一个分区。每个分区最多可以有20亿行)如果我查询同一节点内的数据,检索会很快,我是否正确?我是Cassandra的新手,对分区键和聚类键有点困惑。

我的大部分查询如下:

  • 选择知道的deviceid和tagid的最新时间戳
  • 选择已知deviceid的decvalue和tagid以及时间戳
  • 选择已知deviceid的alphavalue以及tagid和timestamp
  • 选择*知道的deviceid和tagid及时间范围
  • 选择具有时间范围的已知deviceid

我将拥有大约2000个deviceid,每个deviceid将有60个tagid / value对。我不确定它是否会包含大量的deviceid,timestamp,tagid / value,tagid / value ....

1 个答案:

答案 0 :(得分:10)

  

我是Cassandra的新手,对分区键和群集键有点困惑。

听起来你理解分区键,所以我只想补充说你的分区键有助于Cassandra找出群集中存储数据的位置(哪个令牌范围)。每个节点负责几个主令牌范围(假设vnode)。将数据写入数据分区时,它将按群集键进行排序。这也是它存储在磁盘上的方式,因此请记住,您的群集键决定了数据在磁盘上的存储顺序。

  

每个分区最多可以有20亿行

这不完全正确。每个分区最多可支持20亿个单元。单元格本质上是列名/值对。您的群集密钥会自行添加到单个单元格中。因此,通过计算为每个CQL行存储的列值来计算单元格,如果使用群集列,则再添加一个。

根据您的宽行结构,您可能会有远远少于20亿行的限制。此外,这只是存储限制。即使您设法在一个分区中存储了100万个CQL行,查询该分区也会返回如此多的数据,以至于它会笨拙且可能超时。

  

如果我在同一节点内查询数据,检索会很快,我是否正确?

它至少比击中多个节点的多键查询更快。但是它是否“快速”取决于其他因素,例如行的宽度,以及删除和就地更新等操作的频率。

  

我的大部分查询如下:

select lastest timestamp of know deviceid and tagid
Select decvalue of known deviceid and tagid and timestamp
Select alphavalue of known deviceid and tagid and timestamp
select * of know deviceid and tagid with time range
select * of known deviceid with time range

您当前的数据模型可以支持所有这些查询,最后一个除外。要在timestamp上执行范围查询,您需要将数据复制到新表中,并构建PRIMARY KEY以支持该查询模式。这称为“基于查询的建模”。我会建立一个这样的查询表:

CREATE TABLE newdata_by_deviceid_and_time (
  timestamp timestamp,
  deviceid int,
  tagid int,
  decvalue decimal,
  alphavalue text,
  PRIMARY KEY (deviceid,timestamp));

该表可以支持timestamp上的范围查询,同时在deviceid上进行分区。

但我对这两种模型中看到的最大问题是“无限行增长”。基本上,当您为设备收集越来越多的值时,每个分区将接近20亿个单元格限制(同样,在此之前,事情可能会变慢)。您需要做的是使用称为“时间分组”的建模技术。

对于这个例子,我会说我确定按月划分将使我保持在20亿个单元格限制允许我需要的日期范围灵活性类型。如果是这样,我会添加一个额外的分区键monthbucket,我的(新)表将如下所示:

CREATE TABLE newdata_by_deviceid_and_time (
  timestamp timestamp,
  deviceid int,
  tagid int,
  decvalue decimal,
  alphavalue text,
  monthbucket text,
  PRIMARY KEY ((deviceid,monthbucket),timestamp));

现在,当我想查询特定设备和日期范围内的数据时,我还会指定monthbucket

SELECT * FROM newdata_by_deviceid_and_time
WHERE deviceid='AA23' AND monthbucket='201603'
AND timestamp >= '2016-03-01 00:00:00-0500'
AND timestamp < '2016-03-16 00:00:00-0500';

请记住,monthbucket只是一个例子。对于您来说,使用季度甚至年份可能更有意义(假设您一年内每deviceid不存储太多值)。