按时间戳在Cassandra订购最新记录

时间:2015-07-10 13:03:43

标签: cassandra time-series

我试图从传感器列表中显示最新值。该列表也应按时间戳排序。

我尝试了两种不同的方法。我在主键中包含了传感器的更新时间:

CREATE TABLE sensors (
    customerid int,
    sensorid int,
    changedate timestamp,
    value text,
    PRIMARY KEY (customerid, changedate)
) WITH CLUSTERING ORDER BY (changedate DESC);

然后我可以选择这样的列表:

select * from sensors where customerid=0 order by changedate desc;

结果如下:

 customerid | changedate               | sensorid | value
------------+--------------------------+----------+-------
          0 | 2015-07-10 12:46:53+0000 |        1 |     2
          0 | 2015-07-10 12:46:52+0000 |        1 |     1
          0 | 2015-07-10 12:46:52+0000 |        0 |     2
          0 | 2015-07-10 12:46:26+0000 |        0 |     1

问题是,我不仅得到最新结果,而且还得到所有旧值。

如果我从主键中删除了更改的选项,则选择将一起失败。

InvalidRequest: code=2200 [Invalid query] message="Order by is currently only supported on the clustered columns of the PRIMARY KEY, got changedate"

更新传感器值也无选择:

update overview set changedate=unixTimestampOf(now()), value = '5' where customerid=0 and sensorid=0;
InvalidRequest: code=2200 [Invalid query] message="PRIMARY KEY part changedate found in SET part"

此操作失败,因为changedate是主键的一部分。

有没有办法只存储每个传感器的最新值,还能按时间戳保存表格吗?

修改 与此同时,我尝试了另一种方法,只存储最新值。

我使用了这个架构:

CREATE TABLE sensors (
    customerid int,
    sensorid int,
    changedate timestamp,
    value text,
    PRIMARY KEY (customerid, sensorid, changedate)
) WITH CLUSTERING ORDER BY (changedate DESC);

在插入最新值之前,我会删除所有旧值

DELETE FROM sensors WHERE customerid=? and sensorid=?;

但是这失败了,因为changedate不是WHERE子句的一部分。

2 个答案:

答案 0 :(得分:2)

  

问题是,我不仅得到最新结果,而且还得到所有旧值。

由于您存储在DESC的CLUSTERING ORDER中,因此获取最新记录总是非常容易,您需要做的就是在查询中添加“LIMIT”,即:

select * from sensors where customerid=0 order by changedate desc limit 10;

最多返回最多10条记录的记录。即使您使用限制,您仍然可以保证获得最新记录,因为您的数据是按此方式订购的。

  

如果我从主键中删除了更改的选项,则选择将一起失败。

这是因为您不能在不是聚类键(主键的次要部分)的列上订购,除非可能有二级索引,我不建议这样做。

  

更新传感器值也不是选项

您的更新查询失败,因为在'set'中包含部分主键是不合法的。要完成这项工作,您需要做的就是更新您的查询以在where子句中包含changedate,即:

update overview set value = '5' and sensorid = 0 where customerid=0 and changedate=unixTimestampOf(now())
  

有没有办法只存储每个传感器的最新值,还能按时间戳保存表格吗?

您可以通过创建一个名为“latest_sensor_data”的单独表来执行此操作,该表具有相同的表定义,但主键除外。主键现在是'customerid,sensorid',因此每个传感器只能有1个记录。创建单独表的过程称为denormalization,是一种常见的使用模式,特别是在Cassandra数据建模中。插入传感器数据时,您现在可以将数据插入“传感器”和“latest_sensor_data”。

CREATE TABLE latest_sensor_data (
  customerid int,
  sensorid int,
  changedate timestamp,
  value text,
  PRIMARY KEY (customerid, sensorid)
);

在cassandra 3.0中将会引入'materialized views',这将使您不必要,因为您可以使用物化视图为您完成此任务。

现在执行以下查询:

select * from latest_sensor_data where customerid=0

将为该客户的每个传感器提供最新价值。

我建议将'sensors'重命名为'sensor_data'或'sensor_history',以便更清楚地了解数据是什么。此外,您应该将主键更改为“customerid,changedate,sensorid”,因为这样可以让您在同一天拥有多个传感器(这似乎是可能的)。

答案 1 :(得分:2)

你的第一种方法看起来很合理。如果您在查询中添加“限制1”,则只能获得最新结果,或限制2以查看最新的2个结果等。

如果要从表中自动删除旧值,可以在执行插入时为数据点指定TTL(生存时间)。因此,如果您希望将数据点保留10天,可以通过在插入语句中添加“USING TTL 864000”来实现。或者您可以为整个表设置默认TTL。