我有一张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取代。
答案 0 :(得分:6)
您可以在insert语句中使用TIMESTAMP 子句将数据标记为最新:
使用TIMESTAMP标记插入的数据(写入时间)。输入自纪元(1970年1月1日)以来的时间(以微秒为单位)。默认情况下,Cassandra使用实际写入时间。
从主键中删除dt_time
,仅存储imei
和
在这种情况下,按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
这有几个问题:
如果条目尚不存在,则无效 - 在这种情况下,您可以尝试在尝试更新之前使用INSERT ... IF NOT EXISTS
,或者使用emei
数字预先填充数据库
轻量级事务会在集群上产生开销,因为在写入之前应该读取数据,这可能是服务器上的重要负载,并且吞吐量会降低。
答案 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