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