我无法确定如何跨多个表维护属性更新,以确保数据的一致性。
例如,假设演员和粉丝之间有多对多的关系。粉丝可以支持很多演员,演员有很多粉丝。我制作了几个表来支持我的查询
CREATE TABLE fans (
fan_id uuid,
fan_attr_1 int,
fan_attr_2 int
PRIMARY KEY ((fan_id))
)
CREATE TABLE actors (
actor_id uuid,
actor_attr_1 int,
actor_attr_2 int
PRIMARY KEY ((actor_id))
)
CREATE TABLE actors_by_fan (
fan_id uuid,
actor_id uuid,
actor_attr_1 int,
actor_attr_2 int
PRIMARY KEY (fan_id, actor_id)
)
CREATE TABLE fans_by_actor (
actor_id uuid,
fan_id uuid,
fan_attr_1 int,
fan_attr_2 int
PRIMARY KEY (actor_id, fan_id)
)
我们说我是粉丝而且我在我的设置页面上,我想将fan_attr_1
更改为其他值。
在fans
表上,我可以更新我的属性,因为应用程序知道我的fan_id并且可以关键。
但是,如果没有首先查询与粉丝绑定的actor_ids,我就无法更改fan_attr_1
上的fans_by_actor
。
如果您要更新fans
或actors
的任何属性,则会出现此问题。
我尝试在网上寻找遇到类似问题的人,但我无法找到它们。例如,在Datastax的数据建模课程中,他们将实例与演员和视频一起用于多对多关系,其中他们有表actors_by_video
和videos_by_actor
。该课程与我咨询过的其他在线资源一样,在查询后讨论了建模表,但还没有研究如何维护数据完整性。在actors_by_video
表中,如果我想更改actor的属性会发生什么?是否必须遍历actors_by_video
的每一行才能找到包含actor的分区并更新属性?这听起来非常低效。另一个选择是预先查找视频ID,但我读到其他地方,在写入之前读取的是Cassandra中的反模式。
从数据建模的角度或从CQL的角度来看,解决此问题的最佳方法是什么?
编辑: - 修正句子存根 - 增加了背景和先前的研究
答案 0 :(得分:0)
数据建模
Cassandra不是关系数据库,DataModeling需要遵循一些基本规则,在高层次上,我们的数据模型需要遵循以下目标。
1)在群集周围均匀分布数据
2)最小化读取的分区数
此外,我们应该选择一个大表而不是将其分成多个表并在表之间添加关系。在这种方法中,将发生重复记录。记录重复并不是一个更昂贵的操作,因为它只需要更多的磁盘空间而不是CPU,内存,磁盘IOP或网络。
请注意,列键名称和值存在大小限制。最大列键(和行键)大小为64KB。最大列值大小为2 GB。但是因为没有流,并且在请求时将整个值提取到堆内存中,将大小限制为仅几MB。
更多信息:
http://www.datastax.com/dev/blog/basic-rules-of-cassandra-data-modeling
http://www.ebaytechblog.com/2012/07/16/cassandra-data-modeling-best-practices-part-1/
http://www.ebaytechblog.com/2012/08/14/cassandra-data-modeling-best-practices-part-2/
https://docs.datastax.com/en/cql/3.1/cql/cql_reference/refLimits.html
CQL
可以使用Batch或Materialized Views维护表间的一致性。物化视图可从3.0版本中获得
请参阅
How to ensure data consistency in Cassandra on different tables?
我的偏好是更改数据模型并进行设计 因此对于我们的查询,如果可能的话,将它作为一个大表。
希望它有帮助!
答案 1 :(得分:0)
物化视图可能是最佳选择:
CREATE MATERIALIZED VIEW actors_by_fan
AS SELECT fan_id, actor_id, actor_attr_1, actor_attr_2
FROM fans
PRIMARY KEY (fan_id, actor_id);
CREATE MATERIALIZED VIEW fans_by_actor
AS SELECT actor_id, fan_id, fan_attr_1, fan_attr_2
FROM actors
PRIMARY KEY (actor_id, fan_id);
在3.0之前的版本中,创建二级索引并评估其性能是否可接受。稍后,升级到3.x后,只需删除二级索引并创建物化视图。
答案 2 :(得分:0)
解决这些问题的方法是手动更新所有已更改的记录。
由于您无法使用实体化视图,因此要更新数据fan_attr_1
,您需要:
fan
。UPDATE fan ... WHERE fan_id = xxx
表
actor_id
actors_by_fan
选择SELECT actor_id ... WHERE fan_id = xxx
中的所有fans_by_actor
。UPDATE fans_by_actor ... WHERE actor_id IN (...)
更新actor_id
表中的所有相应行,或者循环actor_id
并运行每个更新异步。只要您在步骤2中有少量BATCH
,例如少于20,您就可以对所有查询进行分组,并通过在一个numpy.min
中运行它们来保持表之间的强一致性。您需要以其他方式保证表之间的一致性。
这听起来效率低,但我认为还有其他更智能的解决方案。顺便说一句,您发出一个读取(步骤2)和多个写入(步骤1和步骤3)。这不会成为世界的终点,特别是如果你不经常改变所有的属性(例如,每10毫秒)。