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

在 ScyllaDB 和其他 NoSQL 数据库中,数据模型基于查询,而不仅仅是围绕域实体。在创建数据模型时,我们同时考虑了概念数据模型和应用程序工作流:哪些用户将执行哪些查询以及执行频率。

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

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

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

你不应该关注的事情:

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

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

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

什么是主键?

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

1
CREATE TABLE heartrate_v1 (
2
   pet_chip_id uuid,
3
   time timestamp,
4
   heart_rate int,
5
   PRIMARY KEY (pet_chip_id)
6
);

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

对于上表,请执行查询:

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

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

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';

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

1
CREATE TABLE heartrate_v2 (
2
   pet_chip_id uuid,
3
   time timestamp,
4
   heart_rate int,
5
   PRIMARY KEY (pet_chip_id, time)
6
);

并插入一些数据:

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_idtime

主键由两部分组成:

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

eaeac9f5a28d05904905307d0c6a512b.png

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

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

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';

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

读取同一只宠物的数据:

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';

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

1
CREATE TABLE heartrate_v3 (
2
   pet_chip_id uuid,
3
   time timestamp,
4
   heart_rate int,
5
   pet_name text,
6
   PRIMARY KEY ((pet_chip_id, time), pet_name)
7
);

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

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_idtimepet_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_idpet_nameheart_rate

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

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

1
CREATE TABLE heartrate_v4 (
2
   pet_chip_id uuid,
3
   time timestamp,
4
   heart_rate int,
5
   pet_name text,
6
   PRIMARY KEY (pet_chip_id, pet_name, heart_rate)
7
);

注意:

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

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

  • 除了“分区键”列之外,查询还可能包括“群集键”。如果它确实包含“聚类分析键”列,则必须按照定义的顺序使用它们。

  • 23
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晨曦_子画

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值