SQL熟悉的人转向Cassandra/NoSQL的概述

mty*_*son 4 cassandra nosql

经过多年与关系数据库的交易,我很自然 自在 被洗脑了标准化为考虑表,列和行.卡桑德拉仍然无法完全环绕它.

我更了解它的持久性地图,你只能查询这些地图的唯一键,但我的理解是不完整的.

是的,我是RTFM.不过,有人能给我一个很好的,简洁的描述Cassandra如何构建数据与SQL数据库吗?我的意思是,1000英尺的视图,它的工作原理有何不同?

例如,在Ebay技术博客上,它说:

不要想到关系表.

相反,请考虑嵌套的有序地图数据结构.资料来源:http://www.ebaytechblog.com/2012/07/16/cassandra-data-modeling-best-practices-part-1/

而我几乎完全得到它......但并不完全.


这些是一些很好的答案.添加了赏金,看它是否激励任何人做出更具权威性的回应.

Aar*_*ron 6

注意:由于最初的问题是关于Cassandra,这将是这个答案的焦点.虽然Cassandra和其他非关系(NoSQL)数据存储通常会共享相似的概念,但不能假设这里详述的思想可以与其他非关系数据存储一起使用.

解决这个问题的最佳方法是记住,建立适合您查询的数据模型是Cassandra的标准做法.主要区别在于,RDBMS表是以高效存储数据为主要内容构建的.在Cassandra(非关系型)世界中,主要焦点会改变您希望查询的外观.通常情况下,这可能转化为以多种方式存储相同的冗余数据......这没关系.这在DataStax文档中解释,将Cassandra数据模型与关系数据库进行比较.

假设我有以下用户表:

CREATE TABLE users (
    username TEXT,
    firstname TEXT,
    lastname TEXT,
    phone TEXT,
    PRIMARY KEY (username));
Run Code Online (Sandbox Code Playgroud)

插入一些示例数据后,该表如下所示:

username  | firstname | lastname | phone
------------------------------------------------
mreynolds | Malcolm   | Reynolds | 111-555-1234
jcobb     | Jayne     | Cobb     | 111-555-3464
sbook     | Derial    | Book     | 111-555-2349
stam      | Simon     | Tam      | 111-555-8899
Run Code Online (Sandbox Code Playgroud)

users表将允许我查询我的用户username,因为这是我们的PRIMARY KEY.但是,如果我们想通过电话号码查询数据呢?您可能想要添加二级索引phone,但基数phone可能会高达username.解决此问题的正确方法是创建一个新表,以便您通过电话进行查询.注意:此模型假设username并且phone都是唯一的.

CREATE TABLE usersbyphone (
    phone TEXT,
    username TEXT,
    firstname TEXT,
    lastname TEXT,
    PRIMARY KEY (phone));
Run Code Online (Sandbox Code Playgroud)

让我们假设我们的下一个条目是针对用户"Hoban Washburne"和"Zoe Washburne".当他们结婚时,他们将拥有相同的(家庭)电话号码.Cassandra不允许条目共享主键,并将覆盖(最后一个条目获胜).所以我们需要更改usersbyphone表格中的主键,如下所示:

PRIMARY KEY (phone,username));
Run Code Online (Sandbox Code Playgroud)

phone是我们的分区键(用于确定存储此行的分区的键),username是我们的聚类键(用于确定磁盘排序顺序的键).在复合主键中一起使用这两者将确保唯一性.这将允许我们usersbyphone像这样选择我们的表:

SELECT username, firstname, lastnamea, phone FROM usersbyphone;

username  | firstname | lastname | phone
------------------------------------------------
hwashburne| Hoban     | Washburne| 111-555-1212
jcobb     | Jayne     | Cobb     | 111-555-3464
mreynolds | Malcolm   | Reynolds | 111-555-1234
sbook     | Derial    | Book     | 111-555-2349
stam      | Simon     | Tam      | 111-555-8899
zwashburne| Zoe       | Washburne| 111-555-1212
Run Code Online (Sandbox Code Playgroud)

需要注意的是,这是非常重要的usersbyphone表不更换users表...它的工作原理结合它.您将对该数据集有一些需要由users表提供的查询,还有一些需要由usersbyphone表提供.缺点是保持两个表同步是在数据库外部完成的,通常由您的应用程序代码完成.这是一个示例,说明您的思维在非关系范式中必须有何不同.

正如DataStax MVP John Berryman所解释的那样(理解CQL3映射到Cassandra的内部数据结构),Casssandra将把我们的users数据存储在一个如下所示的结构中:

RowKey:mreynolds
=> (column=, value=, timestamp=1374546754299000)
=> (column=firstname, value=Malcolm, timestamp=1374546754299000)
=> (column=lastname, value=Reynolds, timestamp=1374546754299000)
=> (column=phone, value=111-555-1234, timestamp=1374546754299000)
------------------------------------------------------
RowKey:hwashburne
=> (column=, value=, timestamp=1374546757815000)
=> (column=firstname, value=Hoban, timestamp=1374546757815000)
=> (column=lastname, value=Washburne, timestamp=1374546757815000)
=> (column=phone, value=111-555-1212, timestamp=1374546757815000)
------------------------------------------------------
RowKey:zwashburne
=> (column=, value=, timestamp=1374546761055000)
=> (column=firstname, value=Zoe, timestamp=1374546761055000)
=> (column=lastname, value=Washburne, timestamp=1374546761055000)
=> (column=phone, value=111-555-1212, timestamp=1374546761055000)
Run Code Online (Sandbox Code Playgroud)

Map-of-a-Map概念(在eBay文章中提到)肯定会在这里发挥作用.我们的usersbyphone表格与我们的users表格略有不同:

RowKey:111-555-1234
=> (column=mreynolds, value=, timestamp=1374546754299000)
=> (column=mreynolds:firstname, value=Malcolm, timestamp=1374546754299000)
=> (column=mreynolds:lastname, value=Reynolds, timestamp=1374546754299000)
------------------------------------------------------
RowKey:111-555-1212
=> (column=hwashburne, value=, timestamp=1374546757815000)
=> (column=hwashburne:firstname, value=Hoban, timestamp=1374546757815000)
=> (column=hwashburne:lastname, value=Washburne, timestamp=1374546757815000)
=> (column=zwashburne, value=, timestamp=1374546761055000)
=> (column=zwashburne:firstname, value=Zoe, timestamp=1374546761055000)
=> (column=zwashburne:lastname, value=Washburne, timestamp=1374546761055000)
Run Code Online (Sandbox Code Playgroud)

由于主键结构,请注意Wash(hwashburne)和Zoe(zwashburne)在技术上如何存储在同一行中.此结构允许我们快速查询共享相同电话号码的所有用户.

综上所述:

  • 表(列族)将以最有效的方式用于查询数据.RDBMS鼓励使用规范化来最有效地存储数据.
  • 使用复合键,Cassandra会在附近的行中将类似的数据组合在一起.
  • Cassandra利用磁盘(群集)排序顺序来优化操作.
  • Cassandra主键始终是唯一的.对具有相同主键的数据的不同写入将相互覆盖(最后写入获胜).
  • CQL(Cassandra查询语言)是SQL的有限子集.虽然CQL使用熟悉的语法提供来自RDBMS背景的那些,但重要的是要记住CQL中不存在许多SQL关键字和概念.