围绕电子邮件系统的 Cassandra 数据建模
Posted
技术标签:
【中文标题】围绕电子邮件系统的 Cassandra 数据建模【英文标题】:Cassandra data-modelling around email-system 【发布时间】:2015-04-27 18:29:36 【问题描述】:我需要数据建模帮助,因为我还没有找到解决相同问题的资源。
用户案例类似于电子邮件系统。我想存储用户收到的所有电子邮件的时间线,然后用三种不同的方式取回它们:
-
曾经收到的所有电子邮件
用户已阅读的邮件
用户仍未阅读的邮件
我目前的模型如下:
CREATE TABLE TIMELINE (
userID varchar,
emailID varchar,
timestamp bigint,
read boolean,
PRIMARY KEY (userID, timestamp)
) WITH CLUSTERING ORDER BY (timestamp desc);
CREATE INDEX ON TIMELINE (userID, read);
我需要支持的查询是:
SELECT * FROM TIMELINE where userID = 12;
SELECT * FROM TIMELINE where userID = 12 order by timestamp asc;
SELECT * FROM TIMELINE where userID = 12 and read = true;
SELECT * FROM TIMELINE where userID = 12 and read = false;
SELECT * FROM TIMELINE where userID = 12 and read = true order by timestamp asc;
SELECT * FROM TIMELINE where userID = 12 and read = false order by timestamp asc;
我的查询是:
我是否应该继续阅读作为我的二级索引,因为它会经常更新并且可以创建墓碑 - 每个 http://docs.datastax.com/en/cql/3.1/cql/ddl/ddl_when_use_index_c.html 这是一个问题。
我们可以对二级索引进行不等式检查吗,因为我发现二级索引上应该存在至少一个相等条件
如果这不是正确的建模方式,请就如何支持上述查询提出建议。维护三个不同的表格让我担心插入的数量(对于已读/未读),因为用户数量 * 每天查看的电子邮件将是巨大的。
【问题讨论】:
【参考方案1】:您的索引 (userID) 具有高基数 - 您可能希望将其作为您手动与应用程序同步的第二个(或第三个)CF 进行管理。
可能是这样的
CREATE TABLE READ_TIMELINE (
userID varchar,
emailID varchar,
timestamp bigint,
PRIMARY KEY (userID, timestamp)
) WITH CLUSTERING ORDER BY (timestamp desc);
CREATE TABLE UNREAD_TIMELINE (
userID varchar,
emailID varchar,
timestamp bigint,
PRIMARY KEY (userID, timestamp)
) WITH CLUSTERING ORDER BY (timestamp desc);
这使您能够满足以下查询:
SELECT * FROM READ_TIMELINE where userID = 12;
SELECT * FROM UNREAD_TIMELINE where userID = 12;
SELECT * FROM READ_TIMELINE where userID = 12 order by timestamp asc;
SELECT * FROM UNREAD_TIMELINE where userID = 12 order by timestamp asc;
也就是说,您使用 ORDER BY 的自然聚类顺序,并且您可以通过简单的批处理(一个 DELETE,一个 INSERT)将电子邮件从 UNREAD 移动到 READ
现在,当您将电子邮件标记为已读时,您最终可能会在 UNREAD 表中出现大量墓碑。将 GCGS 设置得较低并使用频繁的压缩可以在一定程度上有所帮助,但是如果您有成千上万的电子邮件飞入并标记为已读,您可能还希望分解这些分区以避免墓碑压倒性问题。
【讨论】:
好答案杰夫。我也在想同样的事情。 这里有一个非常现实的潜在墓碑问题,不容忽视,但我认为这可能是正确的方向。 @JeffJirsa 感谢您的回答和解释。我仍然有一个查询:渲染所有电子邮件时间线 - 我会在 cassandra 上触发两个查询,然后进行内存合并,对吗? 否 - 您将针对 TIMELINE 表执行一次查询,并且仅在需要 WHERE 子句中的读取状态时才使用 READ_TIMELINE 和 UNREAD_TIMELINE。 @JeffJirsa 好的。因此,我们为单个用户维护三个不同的时间线。谢谢。实施后如有更多问题会回复。以上是关于围绕电子邮件系统的 Cassandra 数据建模的主要内容,如果未能解决你的问题,请参考以下文章