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

简介: 在 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

主键由两部分组成:

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

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

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

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.
我们可以按如下方式定义该表:
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

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


目录
相关文章
|
消息中间件 Java 中间件
秒懂消息队列MQ,万字总结带你全面了解消息队列MQ
消息队列是大型分布式系统不可缺少的中间件,也是高并发系统的基石中间件,所以掌握好消息队列MQ就变得极其重要。接下来我就将从零开始介绍什么是消息队列?消息队列的应用场景?如何进行选型?如何在Spring Boot项目中整合集成消息队列。
24472 10
秒懂消息队列MQ,万字总结带你全面了解消息队列MQ
|
6月前
|
安全 API UED
A2A(Agent2Agent) 简介
本文主要介绍Google于2025年4月9日发布的Agent2Agent Protocol(简称“A2A”),这是一个旨在促进不同类型智能体(Agent)之间高效沟通与协作的开放协议。
3723 74
A2A(Agent2Agent) 简介
|
分布式计算 NoSQL Spark
技术好文:scyllaDB基本使用
技术好文:scyllaDB基本使用
|
9月前
|
存储 监控 druid
Druid、ClickHouse、Doris、StarRocks 的区别与分析
本文对比了 Druid、ClickHouse、Doris 和 StarRocks 四款大数据分析引擎。它们均为 OLAP 引擎,采用列式存储和分布式架构,适用于海量数据分析。Druid 擅长实时分析与高并发查询;ClickHouse 以超高性能著称,适合复杂查询;Doris 提供易用的 SQL 接口,性能均衡;StarRocks 则以其极速查询和实时更新能力脱颖而出。各引擎在数据模型、查询性能、数据更新和存储方面存在差异,适用于不同的业务场景。选择时需根据具体需求综合考虑。
4259 20
|
运维 监控 关系型数据库
【一文搞懂PGSQL】7. PostgreSQL + repmgr + witness 高可用架构
该文档介绍了如何构建基于PostgreSQL的高可用架构,利用repmgr进行集群管理和故障转移,并引入witness节点增强网络故障检测能力。repmgr是一款轻量级的开源工具,支持一键部署、自动故障转移及分布式节点管理。文档详细描述了环境搭建步骤,包括配置postgresql参数、安装与配置repmgr、注册集群节点以及配置witness节点等。此外,还提供了故障手动与自动切换的方法及常用命令,确保集群稳定运行。
|
人工智能 搜索推荐 安全
从零到一:微信机器人开发的实战心得
从零到一:微信机器人开发的实战心得
1080 2
|
存储 SQL BI
深入解析实时数仓Doris:介绍、架构剖析、应用场景与数据划分细节
深入解析实时数仓Doris:介绍、架构剖析、应用场景与数据划分细节
|
JavaScript 前端开发
Playwright执行 JavaScript 脚本:探索浏览器自动化的新境界
在Web自动化中,Playwright提供`page.evaluate()`和`page.evaluate_handle()`来执行JavaScript脚本。`page.evaluate()`返回脚本执行结果,而`page.evaluate_handle()`返回JSHandle。示例展示了如何使用它们,如打印网页标题、操作元素及获取页面内容。通过这些方法,可以处理常规方法难以操作的网页元素。
|
NoSQL Oracle 关系型数据库
cassandra使用场景判断:何时使用及何时不用
介绍 我有一个具有以下功能的数据库服务器: 高可用设计。 可以全球分布。 允许应用程序随时随地写入任何节点。 只需向群集添加更多节点即可进行线性扩展。 自动负载及数据均衡。 一种看起来很像SQL的查询语言。
9290 1
|
存储 消息中间件 缓存
【Cassandra从入门到放弃系列 一】概述及基本架构
【Cassandra从入门到放弃系列 一】概述及基本架构
4235 1