时间序列数据的Cassandra分区键

Phu*_* Le 3 php cql cassandra 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));
Run Code Online (Sandbox Code Playgroud)

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

我的大部分查询如下:

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

我将有大约2000个deviceid,每个deviceid将有60个tagid/value对.我不确定它是否会是一行广泛的deviceid,timestamp,tagid/value,tagid/value ....

Aar*_*ron 11

我是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
Run Code Online (Sandbox Code Playgroud)

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

CREATE TABLE newdata_by_deviceid_and_time (
  timestamp timestamp,
  deviceid int,
  tagid int,
  decvalue decimal,
  alphavalue text,
  PRIMARY KEY (deviceid,timestamp));
Run Code Online (Sandbox Code Playgroud)

该表可以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));
Run Code Online (Sandbox Code Playgroud)

现在,当我想查询特定设备和日期范围内的数据时,我还会指定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';
Run Code Online (Sandbox Code Playgroud)

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