22

几天前,我读到了 NoSQL 的宽列存储类型和专门的 Apache-Cassandra。

我的理解是 Cassandra 包括:

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

来自 Stackoverflow 标签:

宽列存储是一种键值对数据库。它使用表、行和列,但与关系数据库不同,列的名称和格式在同一个表中的行与行之间可能会有所不同。

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

但我不明白结构之间的区别:

想象一下我有一个表(或 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);

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

所以我的问题是:

  1. 我对卡桑德拉的想象有什么误解吗?!

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

  3. 是否有任何特殊场景(类似 JSON)无法在关系数据库中实现但 Cassandra 支持?(例如,我知道 Cassandra 不支持嵌套列。)

感谢您的阅读。

4

2 回答 2

15

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

开始:

  • 列族术语在旧的 Thrift API 中使用
  • 在较新的 CQL API 中,使用术语表

表被定义为“多维列族的二维视图”。

术语“宽行”主要与 Thrift API 有关。在 cql 中它的定义有点不同,但下面看起来是一样的。

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

还有更多区别:

  • CQL 可以有存储在分区级别的静态列 - 似乎分区中的每一行都有一个共同的值,但实际上它是存储在上层的单个值。它也可以用于建模 1:N 关系
  • 在 CQL 中,您可以拥有集合类型列 - set、list、map
  • 列可以包含用户定义的类型(您可以定义例如address类型,并在许多地方重用此类型),或者集合可以是用户定义类型的集合
  • 但是 CQL 也不支持 SQL 中可用的 JOIN,并且您必须非常仔细地构建表,因为它们必须严格面向查询(在 cassandra 中,您不能通过任何列值查询数据,二级索引也有很多限制)。通常说,在关系模型中,您清楚地基于数据对表进行建模,而在 cassandra 中,您基于查询进行建模。

我希望我能让你更清楚一点。我建议观看Datastax 核心概念课程中的一些视频(或阅读幻灯片),作为对 Cassandra 的可靠介绍。

于 2016-03-24T22:11:31.750 回答
6

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

SELECT * FROM a_table_here; 

在生产 Cassandra 集群上,因为您在 Coordinator 节点上施加了巨大的负载来聚合来自所有其他节点的所有数据。同样默认情况下,您最多将获得 10000 个“行”。

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

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

接下来是集群列,我不知道您的示例中有没有,但您将它们定义为PRIMARY KEY ((lastname),age, city). 在该示例中,您首先按年龄聚类,然后按城市聚类,这是有序的。

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

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

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

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

于 2016-03-28T05:42:39.193 回答