详解Cassandra数据模型

数据库 其他数据库
本文将为大家介绍的是Cassandra数据模型,希望通过这些例子,能让大家更好的理解NoSQL的精髓。

Cassandra是一个开源的分布式数据库,结合了Dynamo的Key/Value与Bigtable的面向列的特点。

Cassandra的特点如下:

1.灵活的schema:不需要象数据库一样预先设计schema,增加或者删除字段非常方便(on the fly)。

2.支持range查询:可以对Key进行范围查询。

3.高可用,可扩展:单点故障不影响集群服务,可线性扩展。
我们可以将Cassandra的数据模型想象成一个四维或者五维的Hash。

Column

Column是Cassandra中最小的数据单元。它是一个3元的数据类型,包含:name,value和timestamp。

将一个Column用JSON的形式表现出来如下:

  1. {  // 这是一个column     
  2. name: "逖靖寒的世界",    
  3. value: "gpcuster@gmali.com",   
  4. timestamp: 123456789  
  5. }  

为了简单起见,我们可以忽略timestamp。就把column想象成一个name/value即可。

注意,这里提到的name和value都是byte[]类型的,长度不限。

SuperColumn

我们可以将SuperColumn想象成Column的数组,它包含一个name,以及一系列相应的Column。

将一个SuperColumn用JSON的形式表现如下:

  1. {     
  2. // 这是一个SuperColumn     
  3. name: "逖靖寒的世界",  
  4.  // 包含一系列的Columns   
  5. value: {    
  6. street: {name: "street", value: "1234 x street", timestamp: 123456789},     
  7.  city: {name: "city", value: "san francisco", timestamp: 123456789},     
  8. zip: {name: "zip", value: "94107", timestamp: 123456789},    
  9. }    

Columns和SuperColumns都是name与value的组合。最大的不同在于Column的value是一个“string”,而SuperColumn的value是Columns的Map。

还有一点需要注意的是:SuperColumn’本身是不包含timestamp的。

ColumnFamily

ColumnFamily是一个包含了许多Row的结构,你可以将它想象成RDBMS中的Table。

每一个Row都包含有client提供的Key以及和该Key关联的一系列Column。

我们可以看看结构:

  1. UserProfile = {   
  2. // 这是一个ColumnFamily   
  3. phatduckk: {     
  4. // 这是对应ColumnFamily的key    
  5. // 这是Key下对应的Column    
  6.  username: "gpcuster",    
  7.  email: "gpcuster@gmail.com",   
  8. phone: "6666"     
  9.  }, // 第一个row结束   
  10. ieure: {    
  11.  // 这是ColumnFamily的另一个key   
  12. //这是另一个Key对应的column   
  13.  username: "pengguo",   
  14.  email: "pengguo@live.com",    
  15.  phone: "888"   
  16.  age: "66"    
  17.  },    
  18.  }  

ColumnFamily的类型可以为Standard,也可以是Super类型。

我们刚刚看到的那个例子是一个Standard类型的ColumnFamily。Standard类型的ColumnFamily包含了一系列的Columns(不是SuperColumn)。

Super类型的ColumnFamily包含了一系列的SuperColumn,但是并不能像SuperColumn那样包含一系列Standard ColumnFamily。

这是一个简单的例子:

  1. AddressBook = { // 这是一个Super类型的ColumnFamily     
  2. phatduckk: {    // key   
  3.   friend1: {street: "8th street", zip: "90210", city: "Beverley Hills", state: "CA"},   
  4.  John: {street: "Howard street", zip: "94404", city: "FC", state: "CA"},    
  5. Kim: {street: "X street", zip: "87876", city: "Balls", state: "VA"},    
  6. Tod: {street: "Jerry street", zip: "54556", city: "Cartoon", state: "CO"},   
  7. Bob: {street: "Q Blvd", zip: "24252", city: "Nowhere", state: "MN"},    
  8.   ...   
  9.  }, // row结束   
  10.  ieure: {     // key   
  11.     joey: {street: "A ave", zip: "55485", city: "Hell", state: "NV"},    
  12.      William: {street: "Armpit Dr", zip: "93301", city: "Bakersfield", state: "CA"},   
  13.   },    
  14.  }  

Keyspace

Keyspace是我们的数据最外层,你所有的ColumnFamily都属于某一个Keyspace。一般来说,我们的一个程序应用只会有一个Keyspace。

简单测试

我们将Cassandra运行起来以后,启动命令行,执行如下操作:

 

  1. cassandra> set Keyspace1.Standard1['jsmith']['first'] = 'John'   
  2. Value inserted.   
  3. cassandra> set Keyspace1.Standard1['jsmith']['last'] = 'Smith'   
  4. Value inserted.   
  5. cassandra> set Keyspace1.Standard1['jsmith']['age'] = '42'   
  6. Value inserted. 

这个时候,Cassandra中就已经有3条数据了。

其中插入数据的各个字段含义如下:

image 

接下来,我们执行查询操作:

  1. cassandra> get Keyspace1.Standard1['jsmith']   
  2.   (column=agevalue=42timestamp=1249930062801)   
  3.   (column=firstvalue=Johntimestamp=1249930053103)   
  4.   (column=lastvalue=Smithtimestamp=1249930058345)   
  5. Returned 3 rows. 

这样,我们就可以将之前插入的数据查询出来了。

排序

有一点需要明确,我们使用Cassandra的时候,数据在写入的时候就已经排好顺序了。

在某一个Key内的所有Column都是按照它的Name来排序的。我们可以在storage-conf.xml文件中指定排序的类型。

目前Cassandra提供的排序类型有:BytesType, UTF8Type,LexicalUUIDType, TimeUUIDType, AsciiType,和LongType。

现在假设你的原始数据如下:

  1. {name: 123, value: "hello there"},   
  2. {name: 832416, value: "kjjkbcjkcbbd"},   
  3. {name: 3, value: "101010101010"},   
  4. {name: 976, value: "kjjkbcjkcbbd"} 

当我们storage-conf.xml文件中指定排序的类型为LongType时:

<!--
      ColumnFamily 在 storage-conf.xml 中定义
-->
<ColumnFamily CompareWith="LongType" Name="CF_NAME_HERE"/>

排序后的数据就是这样的:

  1. {name: 3, value: "101010101010"},     
  2. {name: 123, value: "hello there"},   
  3. {name: 976, value: "kjjkbcjkcbbd"},   
  4. {name: 832416, value: "kjjkbcjkcbbd"} 

如果我们指定排序的类型为UTF8Type

  1. <!--   
  2.       ColumnFamily 在 storage-conf.xml 中定义  
  3. -->   
  4. <ColumnFamily CompareWith="UTF8Type" Name="CF_NAME_HERE"/> 

排序后的数据就是这样的:

  1. {name: 123, value: "hello there"},      
  2. {name: 3, value: "101010101010"},   
  3. {name: 832416, value: "kjjkbcjkcbbd"},   
  4. {name: 976, value: "kjjkbcjkcbbd"} 

大家可以看到,指定的排序类型不一样,排序的结果也是完全不同的。

对于SuperColumn,我们有一个额外的排序维度,所以我们可以指定CompareSubcolumnsWith来进行另一个维度的排序类型。

假设我们的原始数据如下:

  1. // first SuperColumn from a Row   
  2.     name: "workAddress",   
  3.     // and the columns within it   
  4.     value: {   
  5.         street: {name: "street", value: "1234 x street"},   
  6.         city: {name: "city", value: "san francisco"},   
  7.         zip: {name: "zip", value: "94107"}   
  8.     }   
  9. },   
  10. // another SuperColumn from same Row   
  11.     name: "homeAddress",   
  12.     // and the columns within it   
  13.     value: {   
  14.         street: {name: "street", value: "1234 x street"},   
  15.         city: {name: "city", value: "san francisco"},   
  16.         zip: {name: "zip", value: "94107"}   
  17.     }   

然后我们定义CompareSubcolumnsWith和CompareWith的排序类型都是UTF8Type,那么排序后的结果为:

  1. {   
  2.     // this one's first b/c when treated as UTF8 strings   
  3.     { // another SuperColumn from same Row   
  4.         // This Row comes first b/c "homeAddress" is before "workAddress"              
  5.         name: "homeAddress",   
  6.         // the columns within this SC are also sorted by their names too   
  7.         value: {   
  8.             // see, these are sorted by Column name too   
  9.             city: {name: "city", value: "san francisco"},                  
  10.             street: {name: "street", value: "1234 x street"},   
  11.             zip: {name: "zip", value: "94107"}   
  12.         }   
  13.     },          
  14.     name: "workAddress",   
  15.     value: {   
  16.         // the columns within this SC are also sorted by their names too   
  17.         city: {name: "city", value: "san francisco"},              
  18.         street: {name: "street", value: "1234 x street"},   
  19.         zip: {name: "zip", value: "94107"}   
  20.     }   

再额外提一句,Cassandra的排序功能是允许我们自己实现的,只要你继承org.apache.cassandra.db.marshal.IType就可以了。

原文标题:大话Cassandra数据模型

链接: http://www.cnblogs.com/gpcuster/archive/2010/03/12/1684072.html

【编辑推荐】
  1. 详解NoSQL数据库Apache Cassandra的配置
  2. 漫谈Cassandra客户端的使用
  3. 关系数据库的末日是否已经来临
  4. 超越关系型数据库 pureXML技术应用及展望
  5. 新兴数据库打破整个旧规则
  6. 探寻关系数据库和ORM的最佳替代者
责任编辑:彭凡 来源: 博客园
相关推荐

2022-11-15 08:21:49

物联网数据模型Apache

2021-02-28 22:20:25

2012-03-05 10:54:03

NoSQL

2009-09-18 14:07:51

LINQ to SQL

2021-01-27 05:34:33

Python对象模型

2010-02-22 09:09:02

Visual Stud

2017-06-27 10:08:29

数据仓库模型

2010-08-11 09:29:25

FlexJava数据模型

2016-11-02 12:32:47

数据分析大数据模型

2010-05-31 17:18:39

Cassandra数据

2021-07-14 10:09:05

架构模型数据

2022-08-15 14:49:12

物联网数据模型存储

2022-12-09 09:39:01

数据治理

2010-03-16 14:05:19

Cassandra

2020-10-14 06:28:38

数据仓库模型

2016-01-07 11:25:12

数据模型训练数据

2009-07-20 14:14:03

PowerDesign

2009-11-12 16:39:02

ADO.NET实体数据

2023-02-26 17:46:03

2021-01-15 13:18:39

数据模型领域模型代码
点赞
收藏

51CTO技术栈公众号