GeminiDB Cassandra数据建模
本文介绍GeminiDB Cassandra数据建模的概念,以及针对建模给出的建议。
GeminiDB Cassandra是一款分布式、去中心化、高可用的列存储(Wide Column Store)的NoSQL数据库。分布式层面主要依靠一致性Hash算法把数据分布在整个集群中。
集群中的每个节点将整个Hash范围均匀地分担,每个节点即当做proxy节点,接受client的请求,也负责集群的Primary key range的数据。依赖集群的keyspace的副本策略以及集群的snitch策略,GeminiDB Cassandra将各个节点负责的primary key range复制到集群中其他节点,以提高分布式系统中数据可靠性以及服务可用性。
在GeminiDB Cassandra中,每次读写都会定义一致性级别(即ONE、QUORUM等级别),通过这些可调一致性级别,GeminiDB Cassandra兼顾了服务可用性以及单次请求的数据一致性。
基本概念
Key
GeminiDB Cassandra中有多个key的概念,以下述示例进行描述:
CREATE TABLE mytable1 ( name text PRIMARY KEY , age int , address text , person_id text ); CREATE TABLE mytable2 ( name text , age int , address text , person_id text, PRIMARY KEY (name, age) ); CREATE TABLE mytable3 ( name text , age int , address text , person_id text, PRIMARY KEY ((name, age), person_id) ) WITH CLUSTERING ORDER BY (person_id DESC );
- PRIMARY KEY: 一行数据的唯一标识,由多类数据组成;上面例子中的name、(name, age)、((name, age), person_id) 分别都标识了mytable1、mytable2、mytable3的PRIMARY KEY。
- PARTITION KEY:partition key是PRIMARY KEY的第一列,定义了GeminiDB Cassandra数据在通过Hash以后分布在哪个具体的节点。上述例子中,mytable1、mytable2、mytable3的PARTITION KEY分别是name、name、(name, age)。拥有相同PARTITION KEY的数据一般会存在一个分区下面。
- CLUSTERING KEY:CLUSTERING KEY是PRIMARY KEY除PARTITION KEY的后续列,定义数据在同个分区下面的顺序。上述例子中,mytable1没有CLUSTERING KEY;mytable2、mytable3的CLUSTERING KEY分别是age、person_id。
为了发挥GeminiDB Cassandra集群的性能,我们需要尽量保证集群各个节点的数据量是均匀的。考虑的因素包括:partition size、数据冗余度、磁盘占用空间等。基于最优的性能考虑,建议每个分区下面的数据条数不超过10万,每个分区下面的数据量不超过100MB。
二级索引
以下述为例:
CREATE INDEX mytable_idx_age ON mytable2 (age);
在上述的mytable2上面的列age中建一个native secondary index,因为GeminiDB Cassandra的native secondary index最终是把索引数据放在一张新表,以建索引列的value为key,以索引的原来的key为value,最终的索引表的表结构可能就是:
CREATE TABLE mytable_index_age (age int,name text , address text , person_id text,PRIMARY KEY(age, name));
但是这里的索引表的PARTITION KEY 是不能够让我们根据age找到具体存放索引表的节点,因为索引表的索引数据和原生数据是放在一个节点,使用的是local数据摆放策略。
所以这里建议我们使用native secondary index的时候加上原表的partition限定,这样是最高效的,否则在没有限定partition key的前提下,我们的查找将会涉及到几乎全表扫描的情况。推荐使用如下的使用模式:
SELECT * FROM mytable2 WHERE age = 11 AND name = 'name'; SELECT * FROM mytable2 WHERE age >= 11 AND name IN ('name1', 'name2') ; SELECT * FROM mytable2 WHERE age = 11 AND TOKEN (name)> xxxxx AND TOKEN(name) < yyyyy;
数据模型建立建议和原则
在操作GeminiDB Cassandra之前,需要进行业务建模,基于应用的特性来组织数据(设计primary key)以及存取数据。
- No JOIN:GeminiDB Cassandra不支持JOIN,如果您需要用到JOIN,需要自己在客户端处理,或者再新建一个表进行处理。
- No referential integrity:不支持跨表引用完整性的概念,不支持在某个表中通过外键引用另一张表数据。
- Denormalization:反范式化。
- Query-first的设计:和RDBMS不同的是,优先考虑基于查询进行设计,而不是类似关系数据库,需要优先设计模型。
- Designing for optimal storage:关系型数据库表如何存储是对用户透明的,但是GeminiDB Cassandra的建模需要考虑到数据在磁盘上的存储规则,需要尽量让数据分布的partition少。
- Sorting is a design decision:查询上的排序是在建表时候设定好的。