Apache Cassandra中多对多关系实体的数据建模

62lalag4  于 2023-08-04  发布在  Cassandra
关注(0)|答案(1)|浏览(134)

如何在Cassandra中创建一个包含两个实体的数据模型:合作伙伴和订阅者,其中一个合作伙伴可以有多个订阅者,一个订阅者可以订阅多个合作伙伴。我们正在处理潜在的大数据,即1000万用户和数百个合作伙伴。
最常见的查询是:
1.按合作伙伴名称获取所有订阅者
1.按特定状态按其伙伴名称获取所有订阅者
1.获取在特定日期之后创建的所有合作伙伴/
1.获取具有特定数量订阅者的合作伙伴
由于我是NoSQL世界的新手,目前我只能想到两种方法:
1.在订阅服务器表中创建partner_ids列作为一组合作伙伴ID。那么query将是:SELECT * FROM SUBSCRIBERS WHERE <partner_id>IN partner_ids(我不确定这里的查询性能)
1.创建第三个表PartnerSubscribe表,其中分区键为partner_name,订阅者信息为数据列。我知道反规范化是为了高效查询而建议的,但是在这种情况下,如果有很多订阅者订阅了几十个合作伙伴,就会有大量的重复数据。例如,如果2个合作伙伴拥有相同的600万订户,则该表的大小将不必要地增长。

问题: 如果一个订阅者订阅了多个合作伙伴,我们应该如何处理数据建模以有效地执行上面的查询?*

  • 不好意思,非技术性问题。我只需要对潜在的巨大行的多对多关系中的数据建模有一个基本的了解。提前感谢您 *
bwitn5fc

bwitn5fc1#

一般原则

使用Cassandra进行数据建模与关系数据建模(非常)不同。没有连接,您需要通过反规范化进行。数据将被复制在利润的性能,这是预期的,存储是便宜的。(600万行不算什么)。
DS220 academy.datastax.com上描述了一种数据建模方法,但首先要快速理解的是,大多数情况下,每个查询都有一个表。
当您使用多对多关联时,您将至少需要2个表:

CREATE TABLE IF NOT EXISTS subscribers_by_partner (
   partner_id UUID, 
   subscriber_id UUID
   PRIMARY KEY ((partner_id), subscriber_id)
)

CREATE TABLE IF NOT EXISTS partner_by_subscribers (
   subscriber_id UUID, 
   partner_id UUID
   PRIMARY KEY((subscriber_id), partner_id)
)

字符串
现在我们可以开始考虑

用户查询

幸运的是,您可以使用同一个表实现12

CREATE TABLE IF NOT EXISTS subscribers_by_partner (
 partner_id     UUID,
 state          text,
 subscriber_id  UUID
 PRIMARY KEY((partner_id), state, subscriber_id)
);


你可以和

--- Fetch all subscribers by their partner name
SELECT * FROM subscribers_by_partner where partner_id=....

--- Fetch all subscribers by their partner name by certain state
SELECT * FROM subscribers_by_partner 
where partner_id=.... 
AND state=...

查询合作伙伴

  • 获取在某个日期之后创建的所有合作伙伴
CREATE TABLE IF NOT EXISTS partners_by_subscribers (
 subscriber_id  UUID,
 creation_date  DATE,
 partner_id    UUID,
 PRIMARY KEY((subscriber_id), creation_date, partner_id)
);


在这里,您可以使用:

SELECT * FROM partners_by_subscribers 
WHERE subscriber_id=?
AND creation_date > ?


如果你不想在这里提供订阅者ID,这将是一个完整的扫描表,非常糟糕。你可以按天或按周想组,使不太难看。

CREATE TABLE IF NOT EXISTS partners_by_date (
 yyyymmdd      TEXT,
 creation_date  DATE,
 partner_id    UUID,
 PRIMARY KEY((yyyymmdd), creation_date, partner_id)
);

  • 获取具有特定数量订阅者的合作伙伴

这是一个棘手的计数(*)将超时的大部分时间,不能适用于任何地方。您可以利用计数器,但即使这样,您也需要对集群进行全面扫描,以获取所有合作伙伴的信息。

CREATE TABLE IF NOT EXISTS partner_stats (
 partner_id        UUID
 subscriber_count  counter,
 PRIMARY KEY((partner_id), state)
);

更多见解:

在订阅服务器表中创建partner_ids列作为一组合作伙伴ID。那么query将是:SELECT * FROM SUBSCRIBERS WHERE <partner_id>IN partner_ids(我不确定这里的查询性能)
IN子句的表现非常差,下一个版本的Cassandra将在子句中的18个项目处使用护栏阻止您,因为负载被报告给请求的协调器。
如果有大量的订阅者订阅了几十个合作伙伴,则会产生大量的重复数据。例如,如果2个合作伙伴拥有相同的600万订户,则该表的大小将不必要地增长。
关于Cassandra,这种重复是预料之中的。

相关问题