您链接到的答案是 6 年前的,从那以后 Cassandra 发生了很多变化。Cassandra 刚开始的时候,它的数据模型确实是基于 BigTable 的。一行数据可以包含任意数量的列,每列都有一个名称和一个值。一行可以有一千个不同的列,而不同的行可以有一千个其他列 - 行不必具有相同的列。这样的数据库被称为“无模式”,因为没有每行需要遵守的模式。
但是托托,我们不再在堪萨斯州了——卡桑德拉的模型从那时起就改变了焦点(尽管本质上没有改变),我将尝试解释如何以及为什么:
随着 Cassandra 的成熟,它的开发人员开始意识到无模式并不像他们曾经想象的那么好。模式对于确保应用程序的正确性很有价值。此外,通常不会因为一条记录中有 1000 个单独命名的字段而在一行中达到 1000 列。相反,更常见的情况是记录实际上包含 200 个条目,每个条目有 5 个字段。模式应该修复这些条目中的每一个都应该具有的这 5 个字段,并且定义这些单独条目中的每一个的内容称为“集群键”。所以大约在六年前的 Cassandra 0.8 时代,这些想法被作为“CQL”(Cassandra 查询语言)引入 Cassandra。
例如,在 CQL 中,声明一个列族(它被忠实地重命名为“表”)具有一个模式,其中包含一个已知的字段列表:
CREATE TABLE groups (
groupname text,
username text,
email text,
age int,
PRIMARY KEY (groupname, username)
)
该模式表示表中的每个宽行(现在,在现代 Cassandra 中,这已重命名为“分区”),键为“组名”,可能是一个很长的用户列表,每个用户都有用户名、电子邮件和年龄字段。“PRIMARY KEY”说明符中的第一个名称是分区键(它确定宽行的键),第二个称为集群键(它确定共同构成宽行的小行的键) .
尽管有新的 CQL 换装,Cassandra 继续使用旧的 BigTable-wide-row-without-schema 实现来实现这些新概念。例如,假设我们的数据有一个组“mygroup”,其中有两个人,(john, john@somewhere.com, 27) 和 (joe, joe@somewhere.com, 38)。Cassandra 将以下四个列名 -> 值添加到宽行:
john:email -> john@somewhere.com
john:age -> 27
joe:email -> joe@somewhere.com
joe:age -> 27
请注意我们如何最终得到一个有 4 列的宽行 - 每行 2 个非关键字段(电子邮件和年龄),乘以分区中的行数 (2)。聚类键字段“用户名”不再作为值出现在任何地方,而是作为列名称的一部分!所以如果我们有两个用户名值“john”和“joe”,我们有一些以“john”为前缀的列和一些以“joe”为前缀的列,当我们读取列“joe:email”时,我们知道这是具有 username=joe 的行的电子邮件字段。
Cassandra 仍然具有这种内部二元性——将面向用户的 CQL 行和集群键转换为旧式的宽行。直到最近,Cassandra 的称为“SSTables”的磁盘格式仍然是无模式的,并且使用如上所示的复合名称作为列名。我在 Scylla 的网站https://github.com/scylladb/scylla/wiki/SSTables-Data-File上写了 SSTable 格式的详细说明(Scylla 是我贡献的 Cassandra 的更有效的 C++ 重新实现)。但是,这种格式的列名效率非常低,因此 Cassandra 最近(在 3.0 版中)切换到不同的文件格式,这是第一次接受集群键和模式完整的行作为一等公民。这是 7 年前无模式 Cassandra 棺材上的最后一颗钉子。Cassandra 现在一直是模式完整的。