如何只存储Cassandra最近的条目?

时间:2018-06-15 07:36:13

标签: cassandra datastax datastax-enterprise cassandra-3.0

我有一张Cassandra表: -

create table test(imei text,dt_time timestamp, primary key(imei, dt_time)) WITH CLUSTERING ORDER BY (dt_time DESC);

Partition Key is: imei
Clustering Key is: dt_time

现在我想在每个分区键中仅存储此表中的最新条目(按时间)。 让我们说如果我在一个表中插入条目,每个imei将有单个条目

现在让我们说一个imei 98838377272 dt_time是2017-12-23 16.20.12现在对于相同的imei如果dt_time来2017-12-23 15.20.00 然后不应该在该Cassandra表中插入此条目。

但是如果时间到了2017-12-23 17.20.00那么它应该插入并且上一行应该被这个dt_time取代。

3 个答案:

答案 0 :(得分:6)

您可以在insert语句中使用TIMESTAMP 子句将数据标记为最新:

  

使用TIMESTAMP标记插入的数据(写入时间)。输入自纪元(1970年1月1日)以来的时间(以微秒为单位)。默认情况下,Cassandra使用实际写入时间。

从主键中删除dt_time,仅存储imei

的一个条目
  1. 插入数据并指定时间戳为2017-12-23 16.20.12
  2. 插入数据并指定时间戳为2017-12-23 15.20.00
  3. 在这种情况下,按imei选择将返回带有最新时间戳的记录(从第1点开始)。

    请注意,如果您的dt_time(将指定为时间戳)小于当前时间,则此方法将起作用。换句话说,select query将返回具有最新时间戳但在当前时间之前的记录。如果插入时间戳大于当前时间的数据,则在此时间戳到来之前您将看不到此数据。

答案 1 :(得分:4)

首先,要仅存储表中的最后一个条目,您需要从主键中删除dt_time - 否则您将在每个时间戳中为DB插入条目。

Cassandra支持所谓的lightweight transactions,允许在插入数据之前检查数据。

因此,如果您只想在dt_time小于新时间时更新条目,那么您可以使用以下内容:

首先插入数据:

> insert into test(imei, dt_time) values('98838377272', '2017-12-23 15:20:12');

尝试同时更新数据,或者可能更小

> update test SET dt_time = '2017-12-23 15:20:12' WHERE imei = '98838377272' 
   IF dt_time < '2017-12-23 15:20:12';

 [applied] | dt_time
-----------+---------------------------------
     False | 2017-12-23 15:20:12.000000+0000

这会失败,因为applied等于False。我可以用更大的时间戳更新它,它会更新:

> update test SET dt_time = '2017-12-23 15:20:12' WHERE imei = '98838377272' 
   IF dt_time < '2017-12-23 16:21:12';

 [applied]
-----------
      True

这有几个问题:

  1. 如果条目尚不存在,则无效 - 在这种情况下,您可以尝试在尝试更新之前使用INSERT ... IF NOT EXISTS,或者使用emei数字预先填充数据库

  2. 轻量级事务会在集群上产生开销,因为在写入之前应该读取数据,这可能是服务器上的重要负载,并且吞吐量会降低。

答案 2 :(得分:3)

实际上,您无法“更新”群集密钥,因为它是主键的一部分,因此您应该删除dt_time上的群集密钥。

然后,您可以使用轻量级事务更新行,该事务检查新值是否在现有值之后。

cqlsh:test> CREATE TABLE test1(imei text, dt_time timestamp) PRIMARY KEY (imei);

cqlsh:test> INSERT INTO test1 (imei, dt_time) VALUES ('98838377272', '2017-12-23 16:20:12');
cqlsh:test> SELECT * FROM test1;

 imei        | dt_time
-------------+---------------------------------
 98838377272 | 2017-12-23 08:20:12.000000+0000

(1 rows)

cqlsh:test> UPDATE test1 SET dt_time='2017-12-23 15:20:00' WHERE imei='98838377272' IF dt_time < '2017-12-23 15:20:00';

 [applied] | dt_time
-----------+---------------------------------
     False | 2017-12-23 08:20:12.000000+0000

cqlsh:test> UPDATE test1 SET dt_time='2017-12-23 17:20:00' WHERE imei='98838377272' IF dt_time < '2017-12-23 17:20:00';

 [applied]
-----------
      True

'15:20:00'的更新将返回'false'并告诉您当前值。

'17:20:00'的更新将返回'true'

参考:https://docs.datastax.com/en/cql/3.3/cql/cql_using/useInsertLWT.html