【问题标题】:Order latest records by timestamp in Cassandra在 Cassandra 中按时间戳排序最新记录
【发布时间】:2015-09-29 05:55:24
【问题描述】:

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

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

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

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

如果我从主键中删除 changeate,则选择会一起失败。

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 子句的一部分。

【问题讨论】:

  • 这似乎是检索每组问题中最后一条记录的经典问题。 IE。获取每个传感器 ID 的最新读数。

标签: cassandra time-series


【解决方案1】:

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

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

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

最多将返回 10 条更改日期最高的记录。即使您使用 limit,您仍然可以保证获得最新记录,因为您的数据是按这种方式排序的。

如果我从主键中删除 changeate,则选择会一起失败。

这是因为您不能对不是集群键(主键的次要部分)的列进行排序,除非可能使用辅助索引,我不推荐这样做。

更新传感器值也不是选项

您的更新查询失败,因为在“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 数据建模中。当您插入传感器数据时,您现在会将数据插入到“传感器”和“最新传感器数据”中。

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”,因为这将允许您在同一日期拥有多个传感器(这似乎是可能的)。

【讨论】:

  • 另一个注意事项,如果你想要的不是最新的值(即最后 10 个值),它就会变得更加困难。在 C* 2.2 中,您可以使用用户定义的聚合让 cassandra 按客户为您的传感器表获取每个传感器的 10 个“最新”值。您也可以研究一下,例如使用 spark-cassandra-connector 偶尔为您计算。
  • 你的建议的问题是,我失去了按changedate排序的能力。
  • 我提出 2 个表,一个在 changedate('sensor_history' 表)上有一个集群键,另一个在 sensorid 上集群。
【解决方案2】:

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

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

【讨论】:

  • 我不能在这里使用 TTL,因为没有保证的时间跨度,传感器报告值。它可能会保持沉默数天、数周甚至数月。但我仍然需要保留最新的值。
  • 我认为 OP 想要每个 sensorID 的最新信息。
猜你喜欢
  • 1970-01-01
  • 2018-11-30
  • 1970-01-01
  • 1970-01-01
  • 2021-12-09
  • 2016-08-11
  • 1970-01-01
  • 1970-01-01
  • 2014-04-07
相关资源
最近更新 更多