更新 Cassandra 中的非规范化数据
Posted
技术标签:
【中文标题】更新 Cassandra 中的非规范化数据【英文标题】:Update denormalized data in Cassandra 【发布时间】:2016-10-22 16:15:36 【问题描述】:比方说,我们有可以评论视频的用户,我们希望通过带有用户名的视频显示所有 cmets。 用户也可以访问他的个人资料页面并更改他的名字。
基于此答案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)
);
看起来棒极了,我们只需一个查询就可以获取视频显示 cmets 所需的数据。
现在,让我们考虑这样的用例。
用户创建了很多 cmets(例如 10 000 个),然后决定更改他的名称。 我们应该更新所有 cmets 以更改他的名字吗? 有没有办法让它变得高效?
【问题讨论】:
您对这个问题有更深入的了解吗?我像在这里一样对我的 cmets 进行了非规范化,我想知道如果用户更改它们会发生什么? 【参考方案1】:恭喜,您刚刚进入关系数据库区!
更严重的是,这个要求对您的模型来说是个难题。您必须使用user_id
来查询users
表中users
中的first name
以在读取时为每个cmets 查询,或者您需要查看所有分区和所有cmets 以替换first_name
和last_name
到处。没有办法让它高效。
但是,让我们尝试一种简单的方法。您可以创建一个用户表、一个视频表和另一个存储用户所有 cmets 的表,如下所示:
CREATE TABLE users_videos_comment(
user_id uuid,
video_id uuid,
time timestamp,
comment text,
PRIMARY KEY ((user_id,video_id), time)
);
这对您的新要求很有效,对于一个用户和一个视频,您可以获得所有 cmets,因此您只需查询用户以查找名称,但是您放弃了“一个查询视频中所有 cmets” .此外,您必须在users
中存储用户评论的视频列表,并在videos
中存储制作 cmets 的用户列表。这很难维护,并且会要求更多代码。
也许有更好的方法来做到这一点,但请记住,使用 noSQL 你在写上的松懈,你在读上的收获
如果您不介意进行大量写入来更改用户名,请保持原样。从这个post 来看,Cassandra 似乎更适合写入,因此您应该考虑优化读取。
考虑到这一点,我们可以在users
中添加一个字段,列出用户创建的所有 cmets。这样,您就不必扫描comments_by_video
来查找用户创建的每个 cmets。这增加了一些复杂性,因为对于用户创建的任何 cmets,您必须进行两次写入(并确保它是一致的)。但是你满足了这两个要求。
希望对你有帮助
【讨论】:
它不适合你? 是的,我已经想到了这些选项。对于users_videos_comment
,我们有n + 1
的问题,所以如果视频被1000 个不同的用户评论,那么我们将得到1000 + 1000 + 1(或者只是1000 + 1,以防我们不在@ 中存储名称987654335@)。 videos_where_user_made_comment
或将 cmets/videos 存储在 users
表中似乎是目前最有效的方式。
对不起,我已经删除了我以前的 cmets,因为我无法编辑它。
你看第二种方式了吗?您在视频中列出评论的所有用户的位置?这样您就可以使用 `users_that_comment 检索视频中的 cmets
好吧,如果我理解正确的话。首先,选择通过视频发表评论的用户列表。其次,循环列表并获取cmets。在这种情况下,我们进行n + 1
查询,其中n
发表评论的用户数。因此,最坏的情况是很多用户只发表了一条评论。以上是关于更新 Cassandra 中的非规范化数据的主要内容,如果未能解决你的问题,请参考以下文章