更新 Cassandra 中的非规范化数据

Update denormalized data in Cassandra

比方说,我们有可以对视频发表评论的用户,并且我们希望通过带有用户名的视频显示所有评论。 用户也可以转到他的个人资料页面并更改他的名字。

基于此回答Cassandra denormalization datamodel中涵盖的 Cassandra 数据建模实践,我创建了这样的表:

CREATE TABLE users (
   user_id UUID,
   first_name TEXT,
   last_name TEXT,
   PRIMARY KEY ((user_id))
); 

CREATE TABLE comments_by_video (
   video_id UUID,
   added_at TIMESTAMP,
   user_id UUID,
   comment TEXT,
   first_name TEXT,
   last_name TEXT,
   PRIMARY KEY ((video_id), added_at, user_id)
);

看起来很棒,我们只需一次查询就可以获取显示视频评论所需的数据。

现在,让我们考虑这样的用例。

用户发表了很多评论(比如 10 000 条),然后决定更改他的名字。 我们应该更新所有评论以更改他的名字吗? 有没有办法让它更高效?

恭喜,您刚刚进入关系数据库专区!

更严重的是,这个要求对你的模型来说是一个痛苦。您必须使用 user_id 查询 users table 中的 last_namefirst name 以获取读取时的每个评论,或者您需要查看所有分区和所有注释都替换了 first_namelast_name。没有办法让它变得高效。

但是,让我们尝试一种简单的方法。您可以创建一个用户 table、一个视频 table 和另一个 table 来存储用户的所有评论,例如:

CREATE TABLE users_videos_comment(
    user_id uuid,
    video_id uuid,
    time timestamp,
    comment text,
    PRIMARY KEY ((user_id,video_id), time)
);

这对你的新需求很有效,对于一个用户和一个视频你可以得到所有的评论,所以你只需要查询用户来寻找名字,但是你失去了 "one query for all comments in a video"。此外,您必须在 users 中存储用户发表评论的视频列表,并在 videos 中存储发表评论的用户列表。这很难维护,需要更多代码。

也许有更好的方法来做到这一点,但请记住使用 noSQL 你在写入时失去的东西,你在读取时获得的收益

如果您不介意为更改用户名进行大量写入操作,请保持原样。从这个 post 来看,Cassandra 似乎更适合写入,所以你应该考虑优化读取。

考虑到这一点,我们可以在 users 中添加一个字段,列出用户发表的所有评论。这样,您就不必扫描 comments_by_video 来查找用户发表的每条评论。这增加了一些复杂性,因为对于用户所做的任何评论,您必须进行两次写入(并确保它是一致的)。但是你两个要求都满足了。

希望对您有所帮助