问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

在ScyllaDB(或Cassandra)中使用主键、分区键和群集键

创作时间:
作者:
@小白创作中心

在ScyllaDB(或Cassandra)中使用主键、分区键和群集键

引用
CSDN
1.
https://blog.csdn.net/u013528853/article/details/139516528

在ScyllaDB和Cassandra等NoSQL数据库中,数据模型的设计需要围绕查询需求来展开,而不仅仅是基于域实体。本文将通过一个兽医诊所的案例,详细讲解主键、分区键和集群键的概念及其在实际应用中的重要性。

在ScyllaDB和其他宽列数据库(如Apache Cassandra)中进行数据建模的主要目标之一是快速返回结果。为此,您需要:

  • 均匀的数据分布:数据应均匀分布在集群中,以便每个节点保存大致相同的数据量。ScyllaDB根据分区键的哈希值确定哪个节点应存储数据。因此,选择合适的分区键至关重要。稍后会详细介绍。

  • 若要最大程度地减少读取查询中访问的分区数,请执行以下操作:为了加快读取速度,理想情况下,我们会将读取查询中所需的所有数据存储在单个表中。虽然跨表复制数据是可以的,但就性能而言,如果读取查询所需的数据位于一个表中,则更好。

你不应该关注的事情:

  • 避免数据重复:为了获得高效的读取,我们有时必须复制数据。本课稍后将详细介绍此内容和非规范化。在后面的课程中,我们将学习如何在某些情况下使用二级索引避免重复。

  • 最小化写入次数:ScyllaDB中的写入不是免费的,但它们非常高效且“便宜”。ScyllaDB针对高写入吞吐量进行了优化。读取虽然仍然非常快,但通常比写入更昂贵,并且更难微调。我们通常会准备增加写入次数以提高读取效率。请记住,表的数量也会影响一致性。

在本教程中,您将使用一个名为4Paws Clinic的兽医诊所的示例。在这家诊所,每只入院的动物都有一个连接的心率监测器,每五秒钟记录一次心率和其他重要信息。

什么是主键?

主键在表中定义。它是用于标识行的一列或多列。所有表都必须包含主键的定义。例如,请考虑以下表:

CREATE TABLE heartrate_v1 (
   pet_chip_id uuid,
   time timestamp,
   heart_rate int,
   PRIMARY KEY (pet_chip_id)
);

在上面的示例中,主键是一列——pet_chip_id。如果主键由单个列组成,则称为简单主键。

对于上表,请执行查询:

SELECT * from heartrate_v1 WHERE pet_chip_id = 123e4567-e89b-12d3-a456-426655440b23;

如果我们想通过查询我们的数据,但同时也要通过查询我们的数据,会发生什么?也就是说,如果我们的查询是:

pet_chip_id
time

SELECT * from heartrate_v1 WHERE pet_chip_id = 123e4567-e89b-12d3-a456-426655440b23 AND time >='2019-03-04 07:01:00' AND time <='2019-03-04 07:02:00';

在这种情况下,上述查询将不起作用。我们可以将主键定义为包含多个列,在这种情况下,它称为复合(或复合)键。创建下表:

CREATE TABLE heartrate_v2 (
   pet_chip_id uuid,
   time timestamp,
   heart_rate int,
   PRIMARY KEY (pet_chip_id, time)
);

并插入一些数据:

INSERT INTO heartrate_v2(pet_chip_id, time, heart_rate) VALUES (123e4567-e89b-12d3-a456-426655440b23, '2019-03-04 07:01:05', 100);
INSERT INTO heartrate_v2(pet_chip_id, time, heart_rate) VALUES (123e4567-e89b-12d3-a456-426655440b23, '2019-03-04 07:01:10', 90); 
INSERT INTO heartrate_v2(pet_chip_id, time, heart_rate) VALUES (123e4567-e89b-12d3-a456-426655440b23, '2019-03-04 07:01:50', 96); 
INSERT INTO heartrate_v2(pet_chip_id, time, heart_rate) VALUES (123e4567-e89b-12d3-a456-426655440b23, '2019-04-04 07:01:50', 99);

输入分区键和群集键

在上面显示的情况下,主键的第一部分称为分区键(在上面的示例中),第二部分称为群集键()。

pet_chip_id
time

主键由两部分组成:

  • 分区键负责跨节点分发数据。它确定哪个节点将存储给定的行。它可以是一列或多列。

  • 群集键负责对分区中的行进行排序。它可以是零列或多列。

现在,根据时间执行我们之前看到的查询:

SELECT * from heartrate_v2 WHERE pet_chip_id = 123e4567-e89b-12d3-a456-426655440b23 AND time >='2019-03-04 07:01:00' AND time <='2019-03-04 07:02:00';

此外,我们之前遇到过一个问题,即无论时间如何,宠物都只能记录一个心率值。现在,我们定义了作为主键一部分的时间,每个主键(是pet_chip_idtime的组合)都可以有一个心率值。

heartrate_v1
pet_chip_id
time

读取同一只宠物的数据:

SELECT * from heartrate_v2 WHERE pet_chip_id = 123e4567-e89b-12d3-a456-426655440b23 ;

我们可以看到与前面的例子相反。这一次,该值没有被覆盖。

具有多列的分区键和群集键

正如我们刚才所看到的,分区键和聚类键都可以包含多个列,例如,如果我们的查询是:

SELECT * from heartrate_v3 WHERE pet_chip_id = 123e4567-e89b-12d3-a456-426655440b23 AND time ='2019-03-04 07:01:00' AND pet_name = 'Duke';

我们可以按如下方式定义该表:

CREATE TABLE heartrate_v3 (
   pet_chip_id uuid,
   time timestamp,
   heart_rate int,
   pet_name text,
   PRIMARY KEY ((pet_chip_id, time), pet_name)
);

创建上表,然后插入一些数据:

INSERT INTO heartrate_v3(pet_chip_id, time, heart_rate, pet_name) VALUES (123e4567-e89b-12d3-a456-426655440b23, '2019-03-04 07:01:10', 90, 'Duke');

在本例中,分区键包括两列:pet_chip_idtime,聚类键为pet_name。请记住,每个查询都必须包含分区键中定义的所有列。

pet_chip_id
time
pet_name

现在尝试执行此查询:

SELECT * from heartrate_v3 WHERE pet_chip_id = 123e4567-e89b-12d3-a456-426655440b23;

它失败,因为没有给出整个分区键。

现在试试这个查询:

SELECT * from heartrate_v3 WHERE pet_chip_id = 123e4567-e89b-12d3-a456-426655440b23 AND time ='2019-03-04 07:01:10' AND pet_name = 'Duke';

当给出完整的分区键时,它会成功。

同样,如果我们希望每个分区都基于pet_chip_id但希望能够根据pet_nameheart_rate进行查询:

SELECT * from heartrate_v4 WHERE pet_chip_id = 123e4567-e89b-12d3-a456-426655440b23 AND pet_name = 'Duke' AND heart_rate = 100;

可以定义(执行此操作):

CREATE TABLE heartrate_v4 (
   pet_chip_id uuid,
   time timestamp,
   heart_rate int,
   pet_name text,
   PRIMARY KEY (pet_chip_id, pet_name, heart_rate)
);

注意:

  • 如果聚类分析键(和上面的示例中)中有多个列,则这些列的顺序定义聚类排序。对于给定的分区,所有行在ScyllaDB中按聚类顺序进行物理排序。此顺序决定了可以在此分区上有效运行的选择查询。

pet_name
heart_rate

  • 在此示例中,排序首先是by,然后是。

pet_name
heart_rate

  • 除了“分区键”列之外,查询还可能包括“群集键”。如果它确实包含“聚类分析键”列,则必须按照定义的顺序使用它们。
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号