Difference between partition key, composite key and clustering key in Cassandra?
我一直在阅读网络上的文章,以了解以下
1 2 3 4 | primary key, partition key, composite key clustering key |
围绕这个有很多困惑,我会尽量让它变得简单。
主键是一般概念,用于指示用于从表中检索数据的一个或多个列。
主键可以是SIMPLE,甚至可以内联声明:
1 2 3 4 | create table stackoverflow_simple ( key text PRIMARY KEY, data text ); |
这意味着它是由一个列组成的。
但主键也可以是COMPOSITE(又名COMPOUND),由更多列生成。
1 2 3 4 5 6 | create table stackoverflow_composite ( key_part_one text, key_part_two int, data text, PRIMARY KEY(key_part_one, key_part_two) ); |
在COMPOSITE主键的情况下,键的"第一部分"称为PARTITION KEY(在此示例中,key_part_one是分区键),键的第二部分是CLUSTERING KEY(在此示例中为key_part_two)
请注意,分区和群集键都可以由更多列创建,具体方法如下:
1 2 3 4 5 6 7 8 9 | create table stackoverflow_multiple ( k_part_one text, k_part_two int, k_clust_one text, k_clust_two int, k_clust_three uuid, data text, PRIMARY KEY((k_part_one, k_part_two), k_clust_one, k_clust_two, k_clust_three) ); |
这些名字背后......
- 分区键负责跨节点的数据分发。
- Clustering Key负责分区内的数据排序。
- 主键等同于单字段密钥表中的分区密钥(即简单)。
- 复合/复合键只是任何多列键
进一步的使用信息:DATASTAX文件
小用途和内容示例
简单的关键:
1 2 | insert into stackoverflow_simple (key, data) VALUES ('han', 'solo'); select * from stackoverflow_simple where key='han'; |
表格内容
1 2 3 | key | data ----+------ han | solo |
COMPOSITE / COMPOUND KEY可以检索"宽行"(即,您可以只通过分区键进行查询,即使您已定义了聚类键)
1 2 3 | insert into stackoverflow_composite (key_part_one, key_part_two, data) VALUES ('ronaldo', 9, 'football player'); insert into stackoverflow_composite (key_part_one, key_part_two, data) VALUES ('ronaldo', 10, 'ex-football player'); select * from stackoverflow_composite where key_part_one = 'ronaldo'; |
表格内容
1 2 3 4 | key_part_one | key_part_two | data --------------+--------------+-------------------- ronaldo | 9 | football player ronaldo | 10 | ex-football player |
但您可以使用所有密钥(分区和群集)查询...
1 2 | select * from stackoverflow_composite where key_part_one = 'ronaldo' and key_part_two = 10; |
查询输出
1 2 3 | key_part_one | key_part_two | data --------------+--------------+-------------------- ronaldo | 10 | ex-football player |
重要说明:分区键是使用
如果您有复合分区键,如下所示
例如:
您只能通过至少传递col1和col2来执行查询,这些是定义分区键的2列。要进行查询的"常规"规则是您必须至少传递所有分区键列,然后您可以按照它们设置的顺序可选地添加每个群集键。
所以有效的查询是(不包括二级索引)
- col1和col2
- col1和col2和col10
- col1和col2和col10和col 4
无效:
- col1和col2和col4
- 任何不包含col1和col2的东西
希望这可以帮助。
添加摘要答案作为已接受的答案很长。术语"行"和"列"在CQL的上下文中使用,而不是如何实际实现Cassandra。
- 主键唯一标识一行。
- 复合键是由多列组成的键。
- 分区键是查找一组行(即分区)的主查找。
- 集群密钥是主密钥的一部分,它不是分区密钥(并定义分区内的顺序)。
例子:
-
PRIMARY KEY (a) :分区键是a 。 -
PRIMARY KEY (a, b) :分区键是a ,聚类键是b 。 -
PRIMARY KEY ((a, b)) :复合分区键是(a, b) 。 -
PRIMARY KEY (a, b, c) :分区键是a ,复合聚类键是(b, c) 。 -
PRIMARY KEY ((a, b), c) :复合分区键为(a, b) ,聚类键为c 。 -
PRIMARY KEY ((a, b), c, d) :复合分区键是(a, b) ,复合聚类键是(c, d) 。
在cassandra中,主键,分区键,复合键,聚类键之间的区别总是会产生一些混乱。所以我将在下面解释并与其他人联系起来。我们使用CQL(Cassandra查询语言)进行Cassandra数据库访问。
注意: - 答案是根据Cassandra的更新版本。
首要的关键 :-
在cassandra中有两种不同的方式来使用主键。
1 2 3 4 | CREATE TABLE Cass ( id int PRIMARY KEY, name text ); |
1 2 3 4 5 | Create Table Cass ( id int, name text, PRIMARY KEY(id) ); |
在CQL中,为PRIMARY KEY定义列的顺序很重要。密钥的第一列称为分区密钥,其具有共享相同分区密钥(实际上甚至跨表)的所有行存储在同一物理节点上的属性。此外,对于给定表共享相同分区键的行上的插入/更新/删除是以原子方式单独执行的。注意,可以具有复合分区键,即由多列形成的分区键,使用额外的括号组来定义哪些列形成分区键。
分区和聚类
PRIMARY KEY定义由两部分组成:分区键和聚类列。第一部分映射到存储引擎行键,而第二部分用于对一行中的列进行分组。
1 2 3 4 5 6 7 | CREATE TABLE device_check ( device_id int, checked_at timestamp, is_power boolean, is_locked boolean, PRIMARY KEY (device_id, checked_at) ); |
这里device_id是分区键,checked_at是cluster_key。
我们可以有多个集群密钥以及依赖于声明的分区密钥。
主键:由分区键[和可选的聚类键(或列)组成]
分区键:分区键的哈希值用于确定群集中的特定节点以存储数据
群集密钥:用于对每个分区(或负责节点及其副本)中的数据进行排序
复合主键:如上所述,聚类键在主键中是可选的。如果没有提到它们,它就是一个简单的主键。如果提到了聚类键,则它是复合主键。
复合分区键:仅使用一列作为分区键,可能会导致广泛的行问题(取决于用例/数据建模)。因此,分区键有时被指定为多个列的组合。
关于哪一个是强制性的混淆,哪一个可以在查询中跳过等等,试图将Cassandra想象成一个巨大的HashMap有帮助。因此,在HashMap中,如果没有Key,则无法检索值。这里,分区键起到该键的作用。因此每个查询都需要指定它们。没有它,Cassandra将不知道要搜索哪个节点。
在Cassandra找到负责该特定分区键的特定节点(及其副本)之后,群集键(列是可选的)有助于进一步缩小查询搜索范围。
简而言之:
分区键只是一行的标识,该标识大多数时候是单列(称为主键),有时是多列的组合(称为复合分区键)。
群集密钥只不过是Indexing&排序。群集密钥取决于以下几点:
您在除主键列之外的where子句中使用哪些列。
如果你有非常大的记录,那么我可以分开日期以便于管理。例如,我有一百万个县人口记录的数据。因此,为了便于管理,我基于状态和PIN码后对数据进行聚类等。
Cassandra中的主键通常由两部分组成 - 分区键和聚类列。
primary_key((partition_key),clustering_col)
分区键 - 主键的第一部分。分区键的主要目的是识别存储特定行的节点。
CREATE TABLE phone_book(
phone_num int,
姓名文字,
年龄int,
城市文字,
PRIMARY KEY((phone_num,姓名),年龄);
这里,(phone_num,name)是分区键。在插入数据时,会生成分区键的哈希值,并且该值决定该行应该进入哪个节点。
考虑一个4节点集群,每个节点都有一个可以存储的哈希值范围。
(写)
INSERT INTO phone_book VALUES(7826573732,'Joey',25,'New York');
现在,分区键的哈希值由Cassandra分区器计算。
比如,哈希值(7826573732,'Joey')→12,现在,这一行将被插入到Node C中。
(读)
SELECT * FROM phone_book
WHERE phone_num = 7826573732和name ='Joey';
现在,再次计算分区键的哈希值(7826573732,'Joey'),在我们的情况下为12,它位于节点C中,从中进行读取。
根据您要解决的查询,主键中可以有多个分区键和聚簇列。
primary_key((pk1,pk2),col 1,col2)
值得注意的是,在关系世界(复合键)中,你可能会使用那些更多的类似概念。
示例 - 假设您必须找到最近加入用户组X的最后N个用户。在这种情况下,如果读取占主导地位,您将如何有效地执行此操作?就像那样(来自官方Cassandra指南):
1 2 3 4 5 6 7 8 9 | CREATE TABLE group_join_dates ( groupname text, joined timeuuid, join_date text, username text, email text, age int, PRIMARY KEY ((groupname, join_date), joined) ) WITH CLUSTERING ORDER BY (joined DESC) |
这里,分区键本身是复合键,而聚类键是连接日期。聚类键是连接日期的原因是结果已经排序(并存储,这使得查找速度很快)。但为什么我们使用复合键来分区键?因为我们总是希望尽可能少地读取分区。如何将join_date放在那里有帮助?现在来自同一组和相同加入日期的用户将驻留在一个分区中!这意味着我们将始终尽可能少地读取分区(首先从最新的分区开始,然后转到较旧的分区,依此类推,而不是在它们之间跳转)。
实际上,在极端情况下,您还需要使用join_date的哈希而不是join_date - 这样,如果查询最近3天,那些共享相同的哈希,因此可以从同一个分区获得!
在数据库设计中,复合键是一组非最小的超级键。
复合键是一个包含复合键和至少一个不是超级键的属性的集合
给定表:EMPLOYEES {employee_id,firstname,surname}
可能的超级键是:
1 2 3 | {employee_id} {employee_id, firstname} {employee_id, firstname, surname} |
{employee_id}是唯一的最小超级密钥,它也是唯一的候选密钥 - 假设{firstname}和{surname}不保证唯一性。由于主键被定义为所选择的候选键,并且在该示例中仅存在一个候选键,因此{employee_id}是最小超级键,唯一候选键和唯一可能的主键。
复合键的详尽列表是:
1 2 3 | {employee_id, firstname} {employee_id, surname} {employee_id, firstname, surname} |
唯一的组合键是{employee_id,firstname,surname},因为该键包含复合键({employee_id,firstname})和不是超级键({surname})的属性。