我们大量使用cassandra宽行来存储每个用户的时间序列,因为它们非常适合该用例。我们假设我们有一张表:
create table user_events (
user_id text,
timestmp timestamp,
event text,
primary key((user_id), timestmp));
如果可能发生时间戳冲突(同一用户可以使用相同的时间戳发出两个不同的事件),该怎么办?假设我们对所有事件都有一个排序(每个事件都有一个序列int),调整这个模式来解决这个问题的最佳方法是什么。
如果我按以下方式修改架构:
create table user_events (
user_id text,
timestmp timestamp,
seq int,
event text,
primary key((user_id), timestmp, seq));
我无法做WHERE user_id = ? ORDER BY timestmp ASC, seq ASC
- cassandra不允许这样做。
答案 0 :(得分:0)
我将无法做WHERE user_id =? ORDER BY timestmp ASC,seq ASC - cassandra不允许这样做。
您可能会看到错误,因为您正在重复ASC
。这应该有效:
WHERE user_id = ? ORDER BY timestmp,seq ASC
此外,只要您将主键定义为PRIMARY KEY((user_id),timestmp,seq))
,您甚至不需要指定ORDER BY x[,y] ASC
。它将按顺序将数据聚集在磁盘上,从而将其返回给您已按此顺序排序。只有当您想要按结果降序排列结果时(或者与定义结果相反的情况),才需要ORDER BY
。
如果时间戳发生冲突怎么办?
我认为您的额外seq
列应该足够了,具体取决于您计划插入数据的方式。如果您从客户端设置timestmp
,那么您应该没问题。但是,看看当我(使用你的第二个表)INSERT
行时,以两种不同的方式创建时间戳时会发生什么。
INSERT INTO user_events(user_id,timestmp,seq,event) VALUES ('Mal',dateof(now()),1,'commanding');
INSERT INTO user_events(user_id,timestmp,seq,event) VALUES ('Wash',dateof(now()),1,'piloting');
INSERT INTO user_events(user_id,timestmp,seq,event) VALUES ('River',dateof(now()),1,'freaking out');
INSERT INTO user_events(user_id,timestmp,seq,event) VALUES ('River',dateof(now()),3,'being weird');
INSERT INTO user_events(user_id,timestmp,seq,event) VALUES ('River',dateof(now()),2,'killing reavers');
INSERT INTO user_events(user_id,timestmp,seq,event) VALUES ('River','2015-01-13 13:14-0600',1,'freaking out');
INSERT INTO user_events(user_id,timestmp,seq,event) VALUES ('River','2015-01-13 13:14-0600',3,'being weird');
INSERT INTO user_events(user_id,timestmp,seq,event) VALUES ('River','2015-01-13 13:14-0600',2,'killing reavers');
通过user_id
“River”查询该数据会产生:
aploetz@cqlsh:stackoverflow> SELECT * FROM user_events WHERE user_id='River';
user_id | timestmp | seq | event
---------+--------------------------+-----+-----------------
River | 2015-01-13 13:14:00-0600 | 1 | freaking out
River | 2015-01-13 13:14:00-0600 | 2 | killing reavers
River | 2015-01-13 13:14:00-0600 | 3 | being weird
River | 2015-01-14 12:58:41-0600 | 1 | freaking out
River | 2015-01-14 12:58:57-0600 | 3 | being weird
River | 2015-01-14 12:58:57-0600 | 2 | killing reavers
(6 rows)
请注意,使用now()
函数生成timeuuid,然后将其转换为带dateof()
的时间戳会导致带有timestmp的两行“2015-01-14 12:58:57- 0600“看起来是一样的。但它们并不相同,正如您在seq
列中所说的那样。
所以在使用/生成时间戳时要小心一点。它们可能看起来相同,但它们可能不会存储为相同的值。为了安全起见,我会改用timeuuid。