Cassandra 数据模型

Posted

技术标签:

【中文标题】Cassandra 数据模型【英文标题】:Cassandra data model 【发布时间】:2014-04-08 20:28:53 【问题描述】:

我是一名 cassandra 新手,试图了解如何在 cassandra 中对我们当前的 sql 数据进行建模。数据库存储文档元数据,其中包括 document_id、last_modified_time、size_in_bytes 以及许多其他数据,并且文档的数量可以任意大,因此我们正在寻找一种可扩展的存储和查询解决方案。

需要2个范围查询

    选择 last_modified_time >=x 和 last_modified_time 的所有文档 选择所有尺寸 >= x 和尺寸

还有一组查询,其中文档需要按特定元数据分组,例如

    选择用户在 (x,y,z) 中的所有文档

根据这些查询设计数据模型的最佳做法是什么?

我最初的想法是有一个表(在 Cassandra 2.0,CQL 3.0 中),其中 last_mod_time 作为二级索引,如下所示

创建表 t_document ( 文档 ID 大整数, last_mod_time bigint , 大小大整数, 用户文本, …… 主键(document_id,last_mod_time)

这应该处理查询 1。

我是否需要为查询 2 创建另一个主键为 (document_id, size) 的表?或者我可以将大小添加为同一个表的主键中的第三项,例如(document_id、last_mod_time、大小)。但是在这种情况下,第二个查询是否会在 where 子句中不使用 last_mod_time 的情况下工作?

对于一个或多个用户的所有文档的查询 3,创建一个主键为 (user, doc_id) 的 t_user_doc 表是最佳实践吗?或者更好的方法是在同一个 t_document 表上为用户创建二级索引?

感谢您的帮助。

【问题讨论】:

【参考方案1】:

谈到不平等时,您在 Cassandra 中没有太多选择。它们必须是前导集群列(或二级索引)。因此数据模型可能如下所示:

CREATE TABLE docs_by_time (
dummy int,
last_modified_time timestamp,
document_id bigint,
size_in_bytes bigint,
PRIMARY KEY ((dummy),last_modified_time,document_id));

“虚拟”列始终设置为相同的值,并被用作占位符分区键,所有数据都存储在单个分区中。

这种数据模型的缺点是,事实上,所有数据都存储在一个分区中。每个分区最多有 20 亿个单元,但更重要的是,单个分区永远不会跨越节点。所以这种方法无法扩展。

您可以在表上创建二级索引:

CREATE TABLE docs (
document_id bigint,
last_modified_time timestamp,    
size_in_bytes bigint,
PRIMARY KEY ((dummy),last_modified_time,document_id));

CREATE INDEX docs_last_modified on docs(last_modified);

但是二级索引有很大的缺点 (http://www.slideshare.net/edanuff/indexing-in-cassandra),不建议用于高基数的数据。您可以通过降低 last_modified_time 的精度来缓解基数问题,例如,只存储天组件。

【讨论】:

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

难以定义 Cassandra 数据模型

Cassandra 学习三 数据模型

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

Cassandra 非规范化数据模型

Cassandra的数据模型的理解

时间序列的 Cassandra 数据模型