我有一个由 userId
分发的简单表:
create table test (
userId uuid,
placeId uuid,
visitTime timestamp,
primary key(userId, placeId, visitTime)
) with clustering order by (placeId asc, visitTime desc);
每对
(userId, placeId)
可以有 1 次访问或没有访问。 visitTime
只是一些与之相关的数据,用于在查询中排序,如 select * from test where userId = ? order by visitTime desc
.我怎样才能要求
(userId, placeId)
是独一无二的?我需要确保insert into test (userId, placeId, timeVisit) values (?, ?, ?)
不会插入对
(userId, placeId)
的第二次访问随着不同的时间。在插入之前检查是否存在不是原子的,有没有更好的方法?
最佳答案
让我明白——如果这对夫妇(userId, placeId)
应该是唯一的,(意思是你不必用这对数据放两行)什么是timeVisit
在主键中有用吗?为什么要使用 order by visitTime desc
执行查询如果这将只有一行?
如果您需要的是防止重复,您有两种方法。
1 - 轻量级交易——这个,使用 IF NOT EXISTS
会做你想做的。但正如我所解释的 here由于 cassandra 的特殊处理,轻量级事务真的很慢
2 - USING TIMESTAMP
写入时间强制执行 -(小心!***)“技巧”是强制减少 TIMESTAMP
让我举个例子吧:
INSERT INTO users (uid, placeid , visittime , otherstuffs ) VALUES ( 1, 2, 1000, 'PLEASE DO NOT OVERWRITE ME') using TIMESTAMP 100;
这会产生这个输出
select * from users;
uid | placeid | otherstuffs | visittime
-----+---------+----------------------------+-----------
1 | 2 | PLEASE DO NOT OVERWRITE ME | 1000
现在让我们减少
timestamp
INSERT INTO users (uid, placeid , visittime , otherstuffs ) VALUES ( 1, 2, 2000, 'I WANT OVERWRITE YOU') using TIMESTAMP 90;
现在表中的数据没有更新 ,因为这对夫妇
(uid, placeid)
有更高的 TS 操作 (100) -- 实际上这里的输出没有改变select * from users;
uid | placeid | otherstuffs | visittime
-----+---------+----------------------------+-----------
1 | 2 | PLEASE DO NOT OVERWRITE ME | 1000
如果性能很重要,则使用解决方案 2,如果性能无关紧要,则使用解决方案 1。对于解决方案 2,您可以使用固定数字减去系统时间毫秒来计算每次写入的递减时间戳
例如:
Long decreasingTimestamp = 2_000_000_000_000L - System.currentTimeMillis();
*** 例如,如果您想删除然后重新插入数据,此解决方案可能会导致意外行为。重要的是要知道,一旦删除数据,只有在写入操作将具有更高的删除时间戳时,您才能再次写入它们(如果未指定,则使用的时间戳是机器的时间戳)
哈,
卡罗
关于Cassandra 防止重复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28856303/