我有一个简单的表格,由 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
如果这将只有一行?
如果你需要的是防止重复,你有2种方法。
1 - 轻量级事务 -- 这个,使用 IF NOT EXISTS
会做你想要的事情。但正如我所解释的 此处 由于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;
现在表中的数据还没有更新由于夫妻双方有较高的TS操作(100)。(uid, placeid)
-- 事实上,这里的产出没有改变
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();
*** 这一解决办法可能会导致意外的行为,例如,如果你想删除然后重新插入数据。重要的是,一旦你删除了数据,你将能够再次写入它们,只有当写入操作的时间戳高于删除操作的时间戳(如果没有指定,使用的时间戳是机器的时间戳)。
HTH, Carlo
在Cassandra中,每个主键(行键+聚类键)组合都是唯一的。因此,如果你有一个主键为(A,B,C)的条目,而你插入另一个新的条目,具有相同的(A,B,C)值,旧的条目将被覆盖。
在你的情况下,你的主键中有一个timeVisit属性,这使得在你的情况下无法使用。你可能需要重新考虑你的方案,所以你不需要timeVisit属性。
如果我正确理解了你的要求,你并不真的需要 "时间访问 "属性。visitTime
作为主键的一部分。在你的查询中,你也不需要按主键的 visitTime
因为总是只有一个出现的。userId
placeId
组合。你不需要插入一个没有 "记录 "的 "记录"。visitTime
因为你可以放心地假设,如果你的查询返回0个结果,那么用户从未访问过这个地方。
所以如果你把你的 PRIMARY KEY
只不过 userId
, placeId
那么你可以使用 轻量级交易 来实现你的目标。
你可以使用简单的 insert into test (userId, placeId, timeVisit) values (?, ?, ?) IF NOT EXISTS
的记录,如果已经有一条记录带有所提供的 userId
placeId
组合。