难以定义 Cassandra 数据模型

Posted

技术标签:

【中文标题】难以定义 Cassandra 数据模型【英文标题】:Difficulty in defining Cassandra datamodel 【发布时间】:2014-01-26 08:02:26 【问题描述】:

我是 Casssandra 的新手,我觉得很难实现数据模型。

我在设计一张桌子时遇到了很多问题。

在我提到表定义之前,我想向您展示我们必须检索和更新记录的方式

select * from email where username='suresh' and inactive='N' and type='outbound'
    order by insert_ts desc allow filtering;
update email set inactive='Y' where username='suresh' and inactive='N' 
    and id=101;

要创建一个表,我应该遵循所有 cassandra 定义的规则。我在为表创建索引时遇到了问题

如果我像这样创建主键

PRIMARY KEY(username, inactive,type,insert_ts);

我可以检索记录,但是当我更新时,我收到错误消息“在集合中找到主键部分”错误。

如果我像下面这样创建主键和辅助键

PRIMARY KEY(username, type,insert_ts);
Secondary index = inactive;

我可以进行更新,但是当我检索时,我收到错误消息“二级索引将不允许使用 order by 子句”

我已经使用 cql 之类创建了电子邮件表

Create table email(id int, username varchar, comment text, 
  inactive boolean, insert_ts timestamp, type varchar,
PRIMARY KEY(<<some columns yet to decide>>));

请建议我如何创建满足我查询的电子邮件表。

【问题讨论】:

【参考方案1】:

根据您的信息,inactive 不应该是主键的一部分,因为您打算在不创建新行的情况下随时间更改它。使用它作为基本假设,您需要使用PRIMARY KEY(username, type, insert_ts);

您将无法同时按二级索引过滤和使用ORDER BY [anything]。从 2.0.3 开始,查询引擎不允许这样做。有两种可能的缓解方法:

1) 不要将inactive 设为索引,也不要将其用于过滤。

鉴于您的示例,inactive 似乎是一个低基数值(Y 或 N),此外,您一次操作几行(您通过 username 和/或 @987654327 限制查询@)。因此,就结果数量而言,从查询中省略 inactive 应该不会很昂贵。使用SELECT 时,您可以在客户端过滤inactive 行。

2) 不要使用ORDER BY 时间戳

与上面相同,除了在客户端进行过滤,您现在负责在客户端进行排序。

应根据您的数据和用例来决定哪种缓解措施更合适。我的直觉是,#1 是最好的方法,因为您引入了一个极低的基数,可能会频繁更新索引,以增加便利性。

【讨论】:

【参考方案2】:

感谢您的回复。

根据您的建议,我了解应从主键中删除基数较低的非活动列。我很好,我将在客户端进行非活动过滤。但是,在客户端过滤 insert_ts 并不能解决我的问题,因为该表中将存在数千条电子邮件记录。

Create table email(id int, username varchar, comment text,
  inactive boolean, insert_ts timestamp, type varchar,
PRIMARY KEY(username,type,insert_ts, id))
With Clustering(Type ASC, insert_ts desc, id asc);

我还想在主键中添加 ID 列,因为我们需要显示限制为 100 条的电子邮件记录。Cassandra 有 Limit 子句负责过滤,我可以使用 id 值查找下一个 100 条记录。

例如:

Select * from email where username='suresh' and type='outbound' 
  order by type,insert_ts desc, id 
Limit 101;

在这种情况下,我知道 101 条记录 ID,我将它用于需要获取下 100 条记录的请求。

我希望我能很好地理解它。如果您发现任何差距,请告诉我。

【讨论】:

根据您目前提供的内容,您应该没有问题基于 insert_ts 进行过滤或排序。因为它是插入一行后永远不会改变的东西,您可以将其添加到主键中,然后根据原始帖子中的第一个 SELECT 查询在 WHERE 或 ORDER BY 中使用它(唯一的区别是,您不会不再在 WHERE 中处于活动状态)。 至于 id,我不认为你需要一个额外的列来做你想做的事。只需存储主键的最后一个返回值(用户名 + 类型 + insert_ts)并将该值用于分页,不需要额外的列。详情请看这个答案:***.com/questions/11832886/…。

以上是关于难以定义 Cassandra 数据模型的主要内容,如果未能解决你的问题,请参考以下文章

Cassandra 数据模型

Cassandra 数据模型

Cassandra 学习三 数据模型

深度 | Cassandra数据模型设计最佳实践

Cassandra 非规范化数据模型

Cassandra的数据模型的理解