详解Cassandra数据模型中的primary key

来源:互联网 发布:java getclass 编辑:程序博客网 时间:2024/05/19 16:35

Primary key的基本使用方法

Primary key的基本使用方法同关系型数据库中的primary key基本相同,既用来作为某一行数据的主键。我们用一个最基本的Cassandra表来作为例子。这种最基本的表可以被称为“静态表”。示例如下:

CREATE TABLE users (    user_id uuid,    name varchar,    description varchar,    registered_data timestamp,    PRIMARY KEY (user_id));

这个例子中的PRIMARY KEY定义是最简单的一种形式——仅指定某一列作为primary key,起到唯一地确定某一行数据记录的作用。在上面的例子中,也就是唯一地确定某一个userPRIMARY KEY()声明中的第一个参数一般被称作partition key。在Cassandra中,partition key除去唯一地确定某一行数据的作用之外,还起到排序数据及在分布式系统中确定数据的位置的作用(这一点在分布式系统中极其重要)。

当数据被插入一个Cassandra集群中时,第一个步骤是根据所采用的一致性哈希(consistent hash)算法得出数据partition key所对应的哈希值。这个哈希值被用来确定数据应当被放在集群中的哪一个结点以及数据的冗余备份应当被放在哪几个结点。Cassandra默认采用的哈希算法是Murmur3。一致性哈希算法的特点是可以接受任何输入,但总会输出位于固定范围内的(当前集群的结点有对应的)值。简而言之,某一特定的partition key总会对应集群中的某一特定的结点,而这个partition key对应的数据也总是应当在这个结点上被找到。

对于分布式系统而言,这一点极其重要。其原因是如果对某一特定数据,我们无法确定其所对应的结点位置的话,我们就总是需要遍历集群中的每一个结点才能找到需要的数据。对于小规模的集群,这样的操作可能还可以接受。但对于大规模的分布式数据库而言,这将会严重影响整个系统的效率。

Primary key的进阶使用方法

如果Cassandra的表的Primary KEY包含某一数据的多个列,我们称之为“动态表”。如下面的例子所示:

CREATE TABLE user_articles (    user_id uuid,    uploaded_date timestamp,    article_id uuid,    title test,    abstract text,    PRIMARY KEY (user_id, uploaded_date, article_id));

利用这个表我们可以满足对某一用户所发表的文章的查询。在这一例子中PRIMARY KEY()声明包含数据的多个列。与前文所述相同,声明中包含的第一列仍然是数据的partition key。其后所跟的所有的列都称为clustering column。这一点与关系型数据库非常不同。clustering column用来确定数据在partition内部的排列顺序,对上面的例子而言,也就是对于同一个user_id而言,其所对应的所有行的排列顺序。对于这个paimary key,我们的应当这样理解:

  • 第一个元素确定了partition key
  • 第二个元素确定了第一个clustering column,在这个例子中,也就是uploaded_dateuploaded_date是一个时间戳,也就是说,对于同一个partition key而言,数据将会根据时间升序排列。
  • 第三个元素确定了第二个clustering column,在这个例子中,也就是article_idarticle_id是一个uuid,能够唯一地确定某一篇文章。

在插入相应的数据之后,如果我们使用SELECT去查询,那么返回的数据应当是按照uploaded_date升序排列。对于时间相同的,会按照article_id升序排列。如下面的图片所示:

ASC date user_articles

调整clustering column排序的顺序

既然clustering column能够确定某一个partition内数据排列的顺序,调整这个排列的顺序在某些情况下可能会非常有用。调整这个排列的顺序有两种方法:

  1. SELECT执行的时候指定顺序

    我们可以在使用SELECT进行查询的时候使用ORDER BY指定返回的结果的排列顺序。如下面的例子所示:

SELECT * FROM user_articlesWHERE user_id = 12345ORDER BY uploaded_date DESC;

这个例子指定返回的对应于user_id = 12345的文章根据发表的时间降序排序,也就是说新文章考前,就文章靠后。

  1. 指定当前表在存储时候的默认排序顺序

    如果我们总是进行某一特定排列顺序的数据查询,我们可以在使用CREATE创建表的schema的时候就为其指定clustering column排列的默认顺序,从而提高将来查询的效率。这一操作可以通过CLUSTERING ORDER BY实现。如下面的例子所示:

CREATE TABLE user_articles (    user_id uuid,    uploaded_date timestamp,    article_id uuid,    title test,    abstract test,    PRIMARY KEY (user_id, uploaded_date, article_id)) WITH CLUSTERING ORDER BY (uploaded_date DESC, article_id ASC);

插入数据后表格如下面的图片所示:

DESC date user_articles

在这种情况下,根据uploaded_date进行降序排序的操作将会在数据插入时候就默认执行。我们可以看到这种提前根据将来使用需要进行提前优化的操作有可能起到非常好的效果,尤其是对于时序数据来说。比如如果我们想要查询用户最近发表的五篇文章,使用如下的语句就会非常高效地得到所需要的数据:

SELECT *FROM user_articlesWHERE user_id = 12345LIMIT 10;

总结

综上所述,我们可以发现在Cassandra中primary key是非常重要的。primary key不仅可以用来进行数据查询,而且被用来确定数据存储的结构。这一点在未来设计Cassandra的数据模型时候应当特别注意,从而可以针对未来可能的使用情况提前进行一些优化设计。