因为我一直想用Cassandra来存储我们的数字电表中的数据,按照之前的文章(getting-started-time-series-data-modeling)的介绍,Cassandra真的和适合用于存储time series类型的数据,那么我就想要弄清楚,对于下面这张表   
CREATE TABLE temperature (
weatherstation_id text,
event_time timestamp,
temperature text,
PRIMARY KEY (weatherstation_id,event_time));
在插入了下面这些数据之后,他内部究竟是怎么存储的?
INSERT INTO temperature(weatherstation_id,event_time,temperature) VALUES ('1234ABCD','2013-04-03 07:01:00','72F');
INSERT INTO temperature(weatherstation_id,event_time,temperature) VALUES ('1234ABCD','2013-04-03 07:02:00','73F');
INSERT INTO temperature(weatherstation_id,event_time,temperature) VALUES ('1234ABCD','2013-04-03 07:03:00','73F');
INSERT INTO temperature(weatherstation_id,event_time,temperature) VALUES ('1234ABCD','2013-04-03 07:04:00','74F');
如果按照传统的关系数据库的逻辑,那么在数据库中就存在如下行:
weatherstation_id, event_time, temprature
'1234ABCD','2013-04-03 07:01:00','72F'
'1234ABCD','2013-04-03 07:02:00','73F'
'1234ABCD','2013-04-03 07:03:00','73F'
'1234ABCD','2013-04-03 07:04:00','74F'
假如在数据库中真的也是这么存储的,那就和关系数据库一样了,那我继续使用Postgresql就可以了,还来瞎折腾干什么。
但是我真心希望文章getting-started-time-series-data-modeling所介绍的例子是正确的,我希望数据确实是按照下图这种方式来存储的。
也就是同一个温度气象站的所有温度数据全都存储在同一行,row key就是weatherStationId。那么我就想要弄清楚上面这个temperature 表明明只定义了weatherstation_id, event_time, temperature三列,并且weatherstation_id, event_time作为primary key,为什么到存储的时候,event_time的值就变为列名了?这里究竟是一种什么样的转换规则。

 
另外,在很多地方出现的这张图中,这个 row key1究竟是什么,他和primary key之间有什么关系?

 
   在查阅了一些相关的资料,特别是看了understanding-how-cql3-maps-to-cassandras-internal-data-structure这篇文章之后,我感觉这次我真的懂了,下面来详细说说我的理解。
 
 
一、几个基本概念
首先我们来弄清楚几个基本概念
1) Primary Key;
2) Partition Key;
3) Compound Primary key;
4) Composit Partition key;
5) Clustering Key;
6) Row Key;
 
首先给个公式, 
Primary Key = Partition Key + [Clustering Key]
Row Key=PartitionKey
 
这里的意思就是,Primary Key是有Partition Key 和 Clustering key组成的,其中 Clustering key是可选的。
Primary key, Partition key, clustering key都可以由多个字段组成,其中Partition key如果要由多个字段组成,要用小括号括起来。
Row Key就是PartitionKey,也就是一行的唯一标识。
 
下面来给几个例子。
例子1:
CREATE TABLE users (
user_name varchar PRIMARY KEY,
password varchar,
gender varchar,
session_token varchar,
state varchar,
birth_year bigint
);
 
在这例子中:
Primary key = user_name
Partition key = user_name
Clustering key = null
RowKey=user_name;
 
例子2:
CREATE TABLE emp (
empID int,
deptID int,
first_name varchar,
last_name varchar,
PRIMARY KEY (empID, deptID)
);
Primary Key=empId, deptId;
Partition key=empId
Clustering Key=deptId
rowKey=empId
此时的Primary key 就叫做 Compound Primary Key
 
例子3:
CREATE TABLE Cats (
block_id uuid,
breed text,
color text,
short_hair boolean,
PRIMARY KEY ((block_id, breed), color, short_hair)
);
Primary Key = (block_id, breed), color, short_hair
PartitionKey=block_id, breed
ClusteringKey=color, short_hair
rowKey=blockId, breed
此时的Primary key 就叫做 Compound Primary Key
此时的PartitionKey就叫做Composit Partition Key
 
二、Cassandra的表schema与内部存储结构的转换关系
   下面主要借助文章understanding-how-cql3-maps-to-cassandras-internal-data-structure中的几个例子来说明这种转换关系。
 
(1)例子1:
CreateTable employees(
name text PRIMARY KEY,
age int,
role text
);
加上往该表中插入如下几条数据
此时,他在Cassandra内部实际上是这么存储的

可以看到,PartitionKey对应的name的值被作为row key
然后每一行有2列,每一列都包含列名和值,这个看起来和关系数据库区别不大,他相对于关系数据库其实存在数据冗余,就是每一行都单独存储了列名,而不是像关系数据库一样,有一个统一的列名。
 
(2) 例子2
CreateTable employees(
company text,
name text,
age int,
role text,
PRIMARY KEY(company, name)
);
往表内插入了如下数据
此时,在Cassandra内部实际上是这么存的

简单说明下
company 是row key,上面的数据中company只有OSC和RKG两个值,那就是有两个row key,所以在数据库中就有2行。
name是clustering key, 此时就相当于是clusteringkey的值和primary key的每一列一起组成一个组合列名,比如OSC,eric行就组成了eric:age, eric:role两列。而OSC, john行就组成了john:age, john:role两列。
 
(3)例子3
CreateTable example(
A text,
B text,
C text,
D text,
E text,
F text,
PrimaryKey((A,B),C,D)
)
往表中插入如下数据

 此时在Cassandra内部是这么存的,这次不一样的就是,
PartitionKey是CompositPartitionKey,这就导致rowkey是一个组合键,比如下面的a:b, a:n, s:t
并且ClusteringKey也是由多列组成的,这样在和非Primary key的列拼接列名的时候,就要加上两个字段,比如下面的c:d:E, c:d:F

 
三、开篇的那个time series类型数据例子的存储结构
套用上一节的模式,开篇那个表在插入如下数据之后
weatherstation_id, event_time, temprature
'1234ABCD','2013-04-03 07:01:00','72F'
'1234ABCD','2013-04-03 07:02:00','73F'
'1234ABCD','2013-04-03 07:03:00','73F'
'1234ABCD','2013-04-03 07:04:00','74F'
在Cassandra的存储结构是这样的。

 所有在同一个row key中的数据,在硬盘中就是连续存储的。
 
 
参考资料:
3)理解Cassandra的关键概念和数据模型,https://my.oschina.net/silentriver/blog/182678 
4) understanding-how-cql3-maps-to-cassandras-internal-data-structure, https://www.slideshare.net/DataStax/understanding-how-cql3-maps-to-cassandras-internal-data-structure 

Cassandra存储time series类型数据时的内部数据结构?的更多相关文章

  1. asp.net mvc视图中使用entitySet类型数据时提示出错

    asp.net mvc5视图中使用entitySet类型数据时提示以下错误 检查了一下引用,发现已经引用了System.Data.Linq了,可是还是一直提示出错, 后来发现还需要在Views文件夹下 ...

  2. 关于.net 保存 decimal类型数据到SQLServer2012数据库时自动取整的问题

    公司同事问我有没有遇到过decimal类型数据入库时,会自动取整的问题(比如12.3入库后值是12,12.8入库后值是13,入库后自动四舍五入自动取整): 之前就遇到过从数据去decimal类型数据时 ...

  3. .NET向WebService传值为decimal、double、int、DateTime等非string类型属性时,服务器端接收不到数据的问题

    最近在做CRM项目时,使用C#调用SAP PI发布的WebService服务时遇到的问题: 向WebService传值为decimal.double.int.DateTime等非string类型数据时 ...

  4. 【Redis】redis各类型数据存储分析

    一.简介和应用 Redis是一个由ANSI C语言编写,性能优秀.支持网络.可持久化的K-K内存数据库,并提供多种语言的API.它常用的类型主要是 String.List.Hash.Set.ZSet ...

  5. C#中的double类型数据向SQL sqerver 存储与读取问题

    1.存储 由于double类型在SQLsever中并没有对应数据,试过对应float.real类型,发现小数位都存在四舍五入的现象,目前我使用的是decimal类型,用此类型时个人觉得小数位数应该比自 ...

  6. Java操作Redis存储对象类型数据

    背景描述      关于JAVA去操作Redis时,如何存储一个对象的数据,大家是非常关心的问题,虽然官方提供了存储String,List,Set等等类型,但并不满足我们现在实际应用.存储一个对象是是 ...

  7. mysql那些事(2)时间类型数据如何存储

    几乎每次数据库建模的时候,都会遇到时间类型数据存储的问题. mysql存储时间通常选择这四种类型:datetime.timestamp.int和bigint四种方式,到底使用什么类型,需要看具体的业务 ...

  8. Redis数据结构(一)-Redis的数据存储及String类型的实现

    1 引言 Redis作为基于内存的非关系型的K-V数据库.因读写响应快速.原子操作.提供了多种数据类型String.List.Hash.Set.Sorted Set.在项目中有着广泛的使用,今天我们来 ...

  9. InnerException 消息是“反序列化对象 属于类型 *** 时出现错误。读取 XML 数据时,超出最大字符串内容长度配额 (8192)。(注意细节)

    WEB站点在调用我们WCF服务的时候,只要传入的参数过长,就报如下错误: 格式化程序尝试对消息反序列化时引发异常: 尝试对参数 http://tempuri.org/ 进行反序列化时出错: formD ...

随机推荐

  1. Ubuntu纯字符界面的一些设置

    由于Ubuntu的纯字符界面不支持中文显示,所以进行了一些配置,为了更好的显示 1. 把环境语言配置为英文 在用户目录下的".bashrc"文件的结尾处添加以下内容,然后重新登录 ...

  2. Omi教程-通讯通讯攻略大全

    组件通讯 Omi框架组建间的通讯非常遍历灵活,因为有许多可选方案进行通讯: 通过在组件上声明 data-* 传递给子节点 通过在组件上声明 data 传递给子节点 (支持复杂数据类型的映射) 父容器设 ...

  3. Jquery动态增加行和删除行

    $("#add_5").click(function(){ var str_1="<tr> <td><input type=\"t ...

  4. Windows内存管理简介:

    1:连续的内存空间分配: (1)单一连续分配:只能单作业,单任务运行: 分为系统和用户区:用户区是指除了系统需外左右的内存,由于单用户,单任务,要不都被占用,要不全空   (2):固定空间分配:固定分 ...

  5. 2017-2-24 C#基础 for循环的嵌套

    用几个练习题演示一下for循环的嵌套 1.打印以下图形 ★★★★★★★★★★★★★★★ namespace _2017_2_24_for循环的嵌套 { class Program { static v ...

  6. Oracle 生成一张测试表并插入随机数据

    --生成随机表 --CREATE table scott.One_Million as ( SELECT ROWNUM AS T_ID, TRUNC(DBMS_RANDOM.VALUE(, )) 年龄 ...

  7. 蔡勒(Zeller)公式:根据日期推算是星期几

    Zeller's Congruence: w=y + [y/4] + [c/4] - 2c + [26(m+1)/10] + d - 1 公式中的符号含义如下:w:星期: w对7取模得:0-星期日,1 ...

  8. 关于ImageLoader的一些东西

    网络图片异步加载 其实有关图片加载存在这样一个问题,图片的下载始终是一个耗时的操作,这个时候如果把图片加载放在主线程中话的是不明智的,模拟一个这样的场景, 假如在一个listview或Recycler ...

  9. mybatis系列笔记(2)---mapper代理方法

    mapper代理方法 在我们在写MVC设计的时候,都会写dao层和daoimp实现层,但假如我们使用mapper代理的方法,我们就可以不用先daoimp实现类 当然这得需要遵守一些相应的规则: (1) ...

  10. 使用docker-compose 大杀器来部署服务 上

    使用docker-compose 大杀器来部署服务 上 我们都听过或者用过 docker,然而使用方式却是仅仅用手动的方式,这样去操作 docker 还是很原始. 好吧,可能在小白的眼中噼里啪啦的对着 ...