比较 Cassandra 结构与关系数据库

Comparing Cassandra structure with Relational Databases

几天前,我读到关于 NoSQL 的宽列存储类型和 独家 Apache-Cassandra。

据我了解,Cassandra 包括:

一个键空间(如关系数据库中的数据库)并支持许多列族或 tables(与关系数据库中的 table 相同)和无限行。

来自 Whosebug 标签:

A wide column store is a type of key-value database. It uses tables, rows, and columns, but unlike a relational database, the names and format of the columns can vary from row to row in the same table.

在 Cassandra 中,所有行(在 table 中)都应该有一个行键,然后每个行键可以有多个列。 我了解了关系数据库和 NoSQL (Cassandra) 在实现和存储数据方面的差异。

但是我不明白结构的区别:

想象一个场景,我有一个 table(或 Cassandra 中的列族):

当我执行这样的查询 (CQL) 时:

select * from users;

它给了我你所看到的结果:

lastname  | age  | city          | email               
----------+------+---------------+----------------------
      Doe |   36 | Beverly Hills | janedoe@email.com       
    Jones |   35 |        Austin | bob@example.com        
    Byrne |   24 |     San Diego | robbyrne@email.com         
    Smith |   46 |    Sacramento | null                    
   Jones2 | null |        Austin | bob@example.com       

所以我在关系数据库 (MS SQL) 中使用以下查询执行上述场景:

select * from [users] 

结果是:

lastname  | age  | city          | email               
----------+------+---------------+----------------------
      Doe |   36 | Beverly Hills | janedoe@email.com       
    Jones |   35 |        Austin | bob@example.com        
    Byrne |   24 |     San Diego | robbyrne@email.com         
    Smith |   46 |    Sacramento | NULL                    
   Jones2 | NULL |        Austin | bob@example.com       

我知道 Cassandra 支持动态列,我可以通过以下方式执行此操作:

ALTER TABLE users ADD website varchar;

但是它在关系模型中是可用的,例如在mssql中上面的代码也可以实现。类似于:

ALTER TABLE users ADD website varchar(MAX);

我看到的是第一个 select 和第二个 select 结果是一样的。 在 Cassandra 中,他们只是将行键(姓氏)作为独立对象提供,但它与 mssql(以及所有关系数据库)中的唯一字段(如 ID 或文本)相同,我看到 Cassandra 中的列类型是静态的(在我的示例中 varchar)与它在 Whosebug 标签中的描述不同。

所以我的问题是:

  1. 是不是我对Cassandra的想象有误会?!

  2. 那么这两种结构有什么不同呢?!我告诉你结果是一样的。

  3. 有没有什么特殊场景(JSON之类)关系型数据库无法实现,但Cassandra支持? (例如,我知道 Cassandra 不支持嵌套列。)

感谢您的阅读。

我们必须查看更复杂的示例才能看到差异:)

开始:

  • 旧版 Thrift 中使用了列族术语 API
  • 在较新的 CQL API 中, 使用了 table 一词

Table 定义为 "two-dimensional view of a multi-dimensional column family".

术语 "wide-rows" 主要与 Thrift API 有关。在 cql 中它的定义有点不同,但下面看起来是一样的。

比较 SQL 和 CQL。在 SQL table 中是一组行。在简单的示例中,它在 CQL 中看起来是一样的,但事实并非如此。 CQL table 是一组分区,其中每个分区可以只是一行(例如,当您没有集群键时)或多行。包含多行的分区在 Thrift 热学中名为 "wide-row"。要查看它是如何存储在下面的,请阅读例如关于 here.

中的复合键的部分

差异较多:

  • CQL 可以有存储在分区级别的静态列 - 它 似乎分区中的每一行都有一个共同的价值,但实际上它 是存储在上层的单个值。它也可以用于建模 1:N 关系
  • 在 CQL 中,您可以有集合类型的列 - 集合、列表、映射
  • 列可以包含用户定义的类型(您可以将 address 定义为类型,并在许多地方重用该类型),或集合 可以是用户定义类型的集合
  • 但 CQL 也不支持 SQL 中可用的 JOIN,您必须非常小心地构建 table,因为它们必须 严格面向查询(在cassandra中你不能通过任何方式查询数据 列值,二级索引也有很多限制)。这是 通常说在关系模型中你建模 tables 清楚地基于 在数据上,当在 cassandra 中时,您基于查询建模。

我希望我能让你更清楚一点。我建议观看 Datastax Core Concepts Course 的一些视频(或阅读幻灯片)作为对 Cassandra 的可靠介绍。

根据我的经验,CQL 会误导很多人。首先你永远不想做:

SELECT * FROM a_table_here; 

在生产 Cassandra 集群上,因为您在 Coordinator 节点上施加了巨大的负载来聚合来自所有其他节点的所有数据。同样默认情况下,您最多可以返还 10000 "rows".

要了解 Cassandra 如何存储您的数据,我们需要先建立几个术语:

有主键,在您的情况下 lastname,它被散列以确定集群中的哪个节点拥有这个范围,并且它存储在那里(加上任何副本节点)。

接下来是Cluster Columns,我不知道你的例子里有没有,但是你定义的像PRIMARY KEY ((lastname),age, city)。在该示例中,您首先按年龄然后按城市进行聚类,这是有序的。

现在,对于您的用例的 Cassandra 的简单高级视图,它将数据作为 Map 存储到有序的 Multimap:

Doe -> 36:Beverly Hills -> janedoe@email.com

其中 'Doe' 是主键,它告诉您哪个节点具有该行数据。 36:Beverly Hills 是有序聚类键(有序多映射键的一部分)。最后 janedoe@email.com 是 Map to a Multimap 的最终值(可以是多个)。

为了简化示例,我省略了很多麻烦,为了更深入,我强烈建议阅读:http://www.planetcassandra.org/making-the-change-from-thrift-to-cql/