首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Cassandra数据建模

Cassandra数据建模
EN

Stack Overflow用户
提问于 2015-02-09 22:46:43
回答 2查看 579关注 0票数 2

因此,我正在设计这个数据模型来跟踪产品价格。

一个产品可以被多个用户关注,一个用户可以关注多个产品,因此这是一个多对多的关系。产品受到持续跟踪,但只有在与前一个价格不同的情况下,才会插入新的价格。

用户已经为他们关注的产品设置了价格上限,所以每次价格变化时,都会检查偏好,如果价格低于他们的价格,就会通知用户。

因此,最初我想到了以下产品模型:

然而,"subscriberEmails“是一个列表集合,可以处理多达65536个元素。但作为一个大数据解决方案,这是我们不想要的边界。因此,我们最终为此编写了一个单独的表:

因此,现在"usersByProduct“最多可以有20亿列,这很公平。用户偏好被存储在“地图”中,这也是有限的,但我们认为这是一个很好的最大数量的产品,以供用户遵循。

现在我们面临的问题是:

每次我们想要更新产品的价格时,我们都必须像这样进行查询:

代码语言:javascript
复制
INSERT INTO products("Id", date, price) VALUES (7dacedd2-c09b-46c5-8686-00c2a03c71dd, dateof(now()), 24.87);    // Example only

但是INSERT操作不接受除(如果不存在)以外的其他条件子句,这不是我们想要的。只有当价格与前一个不同时,我们才需要更新它,所以这迫使我们进行两个查询(一个用于读取当前值,另一个用于在必要时更新它)。

警局。UPDATE操作确实有IF条件,但这不是我们的情况,因为我们需要插入。

代码语言:javascript
复制
UPDATE products SET date = dateof(now()) WHERE "Id" = 7dacedd2-c09b-46c5-8686-00c2a03c71dd IF price != 20.3;    // example only 
EN

回答 2

Stack Overflow用户

发布于 2015-02-09 23:30:01

不要试图在cassandra数据库上应用普通模型。它可能会起作用,但你会得到糟糕的性能和可伸缩性。

Cassandra数据建模的推荐方法是首先找出对数据库的读查询,并组织数据,使这些读操作成本更低。您可能需要在某种程度上复制写入,但这是可以的,因为在Cassandra中写入非常便宜。

对于您的特定用例,键查询似乎能够让所有用户对产品的价格变化感兴趣,因此您可以为此创建一个表,例如:

create table productSubscriptions ( productId uuid, priceLimit float, createdAt timestamp, email text, primary key (productId,priceLimit,createdAt) );

但是,因为您还需要知道用户的所有产品订阅,所以您都需要一个包含相同数据的用户键表:

create table userProductSubscriptions ( email text, productId uuid, priceLimit float, primary key (email, productId) )

有了这两个表,我猜您可以看到,所有主要查询都可以通过单行select完成,插入/删除也很简单,但需要同步修改这两个表。

显然,您需要更多地充实模式以满足您的全部需求,但这将为您提供一个关于如何考虑cassandra模式的示例。

条件更新问题

对于您的条件插入问题,最简单的答案是:如果您确实需要使用UPDATE (在CQL中update和insert几乎相同),则使用update执行此操作,但这是一个非常昂贵的操作,因此请尽可能避免使用它。

对于您的用例,我会将您的产品表分成三部分:

create table products ( category uuid, productId uuid, url text, price float, primary key (category, productId) ) create table productPricingAudit ( productId uuid, date timestamp, price float, primary key (productId, date) ) create table priceScheduler ( day text, checktime timestamp, productId uuid, url text, primary key (day, checktime) )

products 表可以保存完整的目录,可以选择按类别拆分(因此,列出单个类别中的所有产品是单行选择)

productPricingAudit将有一个带有最新价格的插入,不管它是什么,因为这将允许您调试您可能遇到的任何定价问题

priceScheduler保存给定一天要进行的所有检查,按检查时间排序。每当调度程序运行时,它只需在单行上执行一次列范围查询。

使用这样的模式,您不必关心条件更新,只要更新产品价格,即使价格没有变化,也只需执行3次插入。

票数 2
EN

Stack Overflow用户

发布于 2015-02-10 05:52:34

好的,我将尝试回答我自己的问题:在Cassandra中,除了“如果不存在”之外的条件插入在日期,句号是不受支持的。

最接近的是条件更新,但这在我们的场景中不起作用。所以只剩下一个简单的选择:应用程序端逻辑。这意味着您必须阅读前面的条目并对您的应用程序执行决策。明显的缺点是执行两次查询(一次SELECT和一次INSERT),这明显增加了延迟。

然而,这很适合我们的应用程序,因为每次我们执行查询来将所有应该检查的商品排入队列时,我们也可以选择商品的urls及其当前价格。因此,检查最新价格的工人可以决定是否插入,因为他们有当前价格可供比较。

所以..。类似这样的查询将每X分钟执行一次:

代码语言:javascript
复制
SELECT id, url, price FROM products WHERE "nextCheckTime" < now();    

// example only, wouldn't even work if nextCheckTime is not part of the PK or index

这是在Cassandra集群上执行的一个非常昂贵的操作,因为它必须遍历默认情况下随机存储在不同节点中的所有行。另一个缺点是,我们需要一些关于产品和用户的高级和具体的统计数据。

因此,我们决定在这种特殊情况下,关系数据库将比Cassandra更好地为我们服务。

遗憾的是,我们保留了Cassandra的所有优势(快速插入、易于缩放、内置分片……)并着眼于MySQL集群或主从实现。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28412428

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档