本文针对Cassandra 3.0和CQL3.0介绍
Cassandra的github上已经更新到3.11版本了。
https://github.com/apache/cassandra
在学习Cassandra的过程中感受到了前所未有的迷惑,就一个数据模型,前前后后看了很多介绍和文档,也听过别人讲座,结果现在一回想还是不清楚数据模型是什么,这让我很不能理解,于是今天整理一下。尽量让事情变得简单。下面是一些很具有误导性的地方
一直以KV的角度在学习 Cassandra,但是看文档和各种解释总和KV对不上,明明就是关系表啊,哪里有key value,发现Cassandra 的 github 已经不说自己是KV数据库了,第一句介绍是
Apache Cassandra is a highly-scalable partitioned row store. Rows are organized into tables with a required primary key.
翻译一下,Cassandra 是一个高可扩展的分区行式存储,其中包括一个主键。上来就用KV的思想来学习是不利于理解的,只会越来越乱,但是 Cassandra 也不是完全没有KV的影子,后边具体介绍。
Cassandra 到底是行式存储还是列式存储?现在我觉得,Cassandra 就是 行式存储 ,列存是把相同属性的数据放在一起有利于压缩,但是明显 Cassandra 现在不是这样的。
本文从另外一个角度来理解 Cassandra 数据模型,首先从关系表入手,然后来找哪里是KV。
和关系数据库一样,上来先建 database,在 Cassandra 里叫keyspace。然后建表,Cassandra 里的表有两种叫法,columnfamily(列簇,列的一家人)和 table。两个关键字都可以在CQL中建表使用,下文均用table。
首先建表,必须指定主键primary key,如果不指定会报错。好,先来随便指定几个。
create table test(c1 int,c2 int,c3 int,c4 int,c5 int,c6 int, primary key(c1,c2,c3,c4));
我们建立了一个有6列的表,并指定主键为 c1, c2, c3, c4。
当 select * from test 时,表结构是这样的:
还可以将主键中的前几列加个括号,这时表结构是这样的
create table test(c1 int,c2 int,c3 int,c4 int,c5 int,c6 int, primary key((c1,c2),c3,c4));
可以看到一共有三种颜色的键,红色的为partition key,用来确定数据分区,即partition,蓝色的为clustering key,用来控制一个节点内部数据的存储顺序。当这两种key由多列构成时,可以看成字符串相加当成一个来看。下面我们以下边这种表结构来举例。
首先插入几条数据。插入的数据主键不能为空,和关系数据库中主键的概念一样,唯一确定一行数据,相同主键数据后者会覆盖前者。
我们插入6条数据,这时表长这样。其中有两个partition key,分别是(1,2)和(1,1)。其中(1,2)对应的行会hash到一个节点,(1,1)对应的行会hash到一个节点。
既然是一张关系表,那么key value到底在哪呢?下面以Partition key为(1,1)的节点为例。
其中红色框为partition key,用来分区。对于(1,1)的Partition key,有m=4行clustering key的实例(蓝色框的行数),后面有n=2列普通列(紫色框的列数),这样蓝色框和紫色框一共会组合出m*n=8个key,分别是(1,1,c5),(1,1,c6),(1,2,c5),(1,2,c6)。。。后面则对应8个数据(绿色框,即value)。这样将这m*n个 key和对应的数据在磁盘上排序存储就好了。
由于页面问题,这里排成了两行,其实在磁盘上是顺序存储的,这其实就是行式存储,一个通过主键进行分区排序的关系型表结构。(至于空值存不存还不确定,这里先不画)
对应成key value时,就是个两层key,一层value,
supercolumn(超列):因为性能问题,Cassandra官方也不推荐用了,不要管这个概念了。
De-normalize(反范式):建表结构时可以适当冗余,来应对Cassandra的表结构对查询的限制,提升查询效率。
wide table(宽表,一行20亿个column):一行指同一个partition key,像上边图中的partition key为(1,1)的所有数据称为一行,20亿个column的意思是同一个partition key的行数不超过20亿。为什么是20亿,因为之前Cassandra将partition key组合排序后用int存储,int是4个字节,范围是20亿。现在不清楚具体实现,使用时尽量同一个partition不要包含太多数据。
感谢东哥的指导!
大家有兴趣的可以关注我的公众号(DBDeveloper),涉及分布式数据库、大数据和个人成长分享,欢迎大家一起交流进步