更新 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_name
和 first name
以获取读取时的每个评论,或者您需要查看所有分区和所有注释都替换了 first_name
和 last_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
来查找用户发表的每条评论。这增加了一些复杂性,因为对于用户所做的任何评论,您必须进行两次写入(并确保它是一致的)。但是你两个要求都满足了。
希望对您有所帮助
比方说,我们有可以对视频发表评论的用户,并且我们希望通过带有用户名的视频显示所有评论。 用户也可以转到他的个人资料页面并更改他的名字。
基于此回答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_name
和 first name
以获取读取时的每个评论,或者您需要查看所有分区和所有注释都替换了 first_name
和 last_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
来查找用户发表的每条评论。这增加了一些复杂性,因为对于用户所做的任何评论,您必须进行两次写入(并确保它是一致的)。但是你两个要求都满足了。
希望对您有所帮助