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

use*_*859 7 time-series cassandra

我正在尝试从传感器列表中显示最新值.该列表还应按时间戳排序.

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

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

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

select * from sensors where customerid=0 order by changedate desc;
Run Code Online (Sandbox Code Playgroud)

结果如下:

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

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

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

InvalidRequest: code=2200 [Invalid query] message="Order by is currently only supported on the clustered columns of the PRIMARY KEY, got changedate"
Run Code Online (Sandbox Code Playgroud)

更新传感器值也是没有选择:

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

这会失败,因为changedate是主键的一部分.

有没有可能的方法只存储每个传感器的最新值,并保持按时间戳排序表?

编辑: 在此期间我尝试了另一种方法,只存储最新的值.

我使用了这个架构:

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

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

DELETE FROM sensors WHERE customerid=? and sensorid=?;
Run Code Online (Sandbox Code Playgroud)

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

And*_*ert 4

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

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

select * from sensors where customerid=0 order by changedate desc limit 10;
Run Code Online (Sandbox Code Playgroud)

最多会返回 10 条更改最高的记录。即使您使用限制,您仍然可以保证获得最新记录,因为您的数据是这样排序的。

如果我从主键中删除更改数据,则选择会全部失败。

这是因为您无法对不是聚集键(主键的辅助部分)的列进行排序,除非可能带有辅助索引,但我不建议这样做。

更新传感器值也是没有选择的

您的更新查询失败,因为在“set”中包含部分主键是不合法的。为了使这项工作有效,您需要做的就是更新您的查询以在 where 子句中包含 Changedate,即:

update overview set value = '5' and sensorid = 0 where customerid=0 and changedate=unixTimestampOf(now())
Run Code Online (Sandbox Code Playgroud)

有没有可能的方法来仅存储每个传感器的最新值,并保持表按时间戳排序?

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

CREATE TABLE latest_sensor_data (
  customerid int,
  sensorid int,
  changedate timestamp,
  value text,
  PRIMARY KEY (customerid, sensorid)
);
Run Code Online (Sandbox Code Playgroud)

在 cassandra 3.0 中,将引入“物化视图”,这将不再需要此操作,因为您可以使用物化视图来完成此操作。

现在执行以下查询:

select * from latest_sensor_data where customerid=0
Run Code Online (Sandbox Code Playgroud)

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

我建议将“传感器”重命名为“sensor_data”或“sensor_history”,以使其更清楚数据是什么。此外,您应该将主键更改为“customerid、changedate、sensorid”,因为这将允许您在同一日期拥有多个传感器(这似乎是可能的)。