RDBMS 设计
当您着手构建一个将使用关系数据库的新数据驱动应用程序时,您可能会从将域建模为一组正确规范化的表开始,并使用外键来引用其他表中的相关数据。
下图显示了您如何使用关系数据库模型来表示应用程序的数据存储。关系模型包括几个“联接”表,以便实现概念模型中酒店到兴趣点、房间到设施、房间到可用性和客人到房间(通过预订)的多对多关系。
RDBMS 和 Cassandra 之间的设计差异
让我们花点时间重点介绍一下为 Cassandra 和关系数据库进行数据建模的一些关键差异。
没有联接
您不能在 Cassandra 中执行联接。如果您已经设计了一个数据模型,并且发现您需要类似联接的东西,您将不得不 either 在客户端执行工作,或者创建一个非规范化的第二个表来为您表示联接结果。在 Cassandra 数据建模中,后一种选择是首选。在客户端执行联接应该是一个非常罕见的情况;您真的希望复制(非规范化)数据。
没有引用完整性
尽管 Cassandra 支持轻量级事务和批处理等功能,但 Cassandra 本身没有跨表的引用完整性概念。在关系数据库中,您可以在表中指定外键来引用另一个表中记录的主键。但是 Cassandra 不强制执行此操作。在您的表中存储与其他实体相关的 ID 仍然是一个常见的設計需求,但级联删除等操作不可用。
非规范化
在关系数据库设计中,您经常被教导规范化的重要性。在使用 Cassandra 时,这不是一个优势,因为它在数据模型非规范化时表现最佳。公司最终在关系数据库中对数据进行非规范化的情况很常见。有两个常见的原因。一个是性能。当公司必须对多年的数据进行太多联接时,它们 simply 无法获得所需的性能,因此它们会根据已知的查询进行非规范化。这最终会奏效,但违背了关系数据库的設計意图,最终让人质疑在这种情况下使用关系数据库是否是最佳方法。
关系数据库有目的地进行非规范化的第二个原因是需要保留的业务文档结构。也就是说,您有一个包含表,它引用了许多外部表,这些外部表的数据可能会随着时间的推移而发生变化,但您需要保留包含文档作为历史快照。这里常见的例子是发票。您已经有了客户和产品表,您可能会认为您只需创建一个引用这些表的 invoice 即可。但这在实践中永远不应该这样做。客户或价格信息可能会发生变化,然后您将丢失发票日期发票文档的完整性,这可能会违反审计、报告或法律,并导致其他问题。
在关系世界中,非规范化违反了 Codd 的范式,您应该避免它。但在 Cassandra 中,非规范化是,嗯,完全正常的。如果您的数据模型很简单,则不需要它。但不要害怕它。
从历史上看,Cassandra 中的非规范化需要使用本文档中描述的技术来设计和管理多个表。从 3.0 版本开始,Cassandra 提供了一个名为 物化视图 <materialized-views>
的功能,它允许您基于基本表设计创建数据的多个非规范化视图。Cassandra 在服务器上管理物化视图,包括使视图与表保持同步的工作。
以查询为先的设计
简单来说,关系建模意味着您从概念域开始,然后在表中表示域中的名词。然后,您分配主键和外键来建模关系。当您有多对多关系时,您会创建仅表示这些键的联接表。联接表在现实世界中不存在,是关系模型工作方式的必要副作用。在您将所有表都布局好之后,您可以开始编写查询,这些查询使用键定义的关系将不同的数据组合在一起。关系世界中的查询非常次要。假设只要您正确地对表进行了建模,您就可以始终获取所需的数据。即使您必须使用多个复杂的子查询或联接语句,这通常也是正确的。
相比之下,在 Cassandra 中,您不是从数据模型开始,而是从查询模型开始。您不是先建模数据,然后编写查询,而是使用 Cassandra 对查询进行建模,并让数据围绕它们进行组织。考虑一下您的应用程序将使用的最常见的查询路径,然后创建支持它们的表。
批评者认为,以查询为先的设计对应用程序设计过于限制,更不用说数据库建模了。但期望您认真考虑应用程序中的查询是完全合理的,就像您可能认真考虑关系域一样。您可能会出错,然后您将在两个世界中都遇到问题。或者您的查询需求可能会随着时间的推移而发生变化,然后您将不得不努力更新您的数据集。但这与在 RDBMS 中定义错误的表或需要额外的表没有什么不同。
设计以实现最佳存储
在关系数据库中,表如何在磁盘上存储对用户来说通常是透明的,很少听到关于基于 RDBMS 如何在磁盘上存储表的建议。但是,这是 Cassandra 中的一个重要考虑因素。因为 Cassandra 表都存储在磁盘上的单独文件中,所以将相关列定义在一起放在同一个表中很重要。
在开始在 Cassandra 中创建数据模型时,您会看到的一个关键目标是最大程度地减少必须搜索以满足给定查询的分区数量。因为分区是存储单元,不会跨节点划分,所以搜索单个分区的查询通常会产生最佳性能。
排序是一个设计决策
在 RDBMS 中,您可以通过在查询中使用 ORDER BY
来轻松更改返回记录的顺序。默认排序顺序不可配置;默认情况下,记录按写入顺序返回。如果您想更改顺序,只需修改您的查询,您就可以按任何列列表进行排序。
然而,在 Cassandra 中,排序的处理方式不同;它是一个设计决策。查询可用的排序顺序是固定的,完全由您在 CREATE TABLE
命令中提供的聚类列的选择决定。CQL SELECT
语句确实支持 ORDER BY
语义,但仅以聚类列指定的顺序支持。
材料改编自 Cassandra,The Definitive Guide。由 O’Reilly Media, Inc. 出版。版权所有 © 2020 Jeff Carpenter, Eben Hewitt。保留所有权利。经许可使用。