Apache Cassandra static column 介绍与实战

假设我们有这样的场景:我们想在 Cassandra 中使用一张表记录用户基本信息(比如 email、密码等)以及用户状态更新。我们知道,用户的基本信息一般很少会变动,但是状态会经常变化,如果每次状态更新都把用户基本信息都加进去,势必会让费大量的存储空间。为了解决这种问题,Cassandra 引入了 static column。同一个 partition key 中被声明为 static 的列只有一个值的,也就是只存储一份。

定义 static column

在表中将某个列定义为 STATIC 很简单,只需要在列的最后面加上 STATIC 关键字,具体如下:

CREATE TABLE "iteblog_users_with_status_updates" ("username" text,"id" timeuuid,"email" text STATIC,"encrypted_password" blob STATIC,"body" text,PRIMARY KEY ("username", "id")
);

iteblog_users_with_status_updates 表中我们将 email 和 encrypted_password 两个字段设置为 STATIC 了,这意味着同一个 username 只会有一个 email 和 encrypted_password 。

注意,不是任何表都支持给列加上 STATIC 关键字的,静态列有以下限制。

1、如果表没有定义 Clustering columns(又称 Clustering key),这种情况是不能添加静态列的。如下:

cqlsh:iteblog_keyspace> CREATE TABLE "iteblog_users_with_status_updates_invalid" (...   "username" text,...   "id" timeuuid,...   "email" text STATIC,...   "encrypted_password" blob STATIC,...   "body" text,...   PRIMARY KEY ("username")... );
InvalidRequest: Error from server: code=2200 [Invalid query] message="Static columns are only useful (and thus allowed) if the table has at least one clustering column"

iteblog_users_with_status_updates_invalid 表只有 PRIMARY KEY,没有定义 clustering column,不支持创建 Static columns。这是因为静态列在同一个 partition key 存在多行的情况下才能达到最优情况,而且行数越多效果也好。但是如果没有定义 clustering column,相同 PRIMARY KEY 的数据在同一个分区里面只存在一行数据,本质上就是静态的,所以没必要支持静态列。

2、如果建表的时候指定了 COMPACT STORAGE,这时候也不允许存在静态列:

cqlsh:iteblog_keyspace> CREATE TABLE "iteblog_users_with_status_updates_invalid" (...   "username" text,...   "id" timeuuid,...   "email" text STATIC,...   "encrypted_password" blob STATIC,...   "body" text,...   PRIMARY KEY ("username", "id")... )WITH COMPACT STORAGE;
InvalidRequest: Error from server: code=2200 [Invalid query] message="Static columns are not supported in COMPACT STORAGE tables"

3、如果列是 partition key/Clustering columns 的一部分,那么这个列不能说明为静态列:

cqlsh:iteblog_keyspace> CREATE TABLE "iteblog_users_with_status_updates_invalid" (...   "username" text,...   "id" timeuuid STATIC,...   "email" text STATIC,...   "encrypted_password" blob STATIC,...   "body" text,...   PRIMARY KEY ("username", "id")... );
InvalidRequest: Error from server: code=2200 [Invalid query] message="Static column id cannot be part of the PRIMARY KEY"
cqlsh:iteblog_keyspace> CREATE TABLE "iteblog_users_with_status_updates_invalid" (...   "username" text,...   "id" timeuuid,...   "email" text STATIC,...   "encrypted_password" blob STATIC,...   "body" text,...   PRIMARY KEY (("username", "id"), email)... );
InvalidRequest: Error from server: code=2200 [Invalid query] message="Static column email cannot be part of the PRIMARY KEY"

给静态列的表插入数据

含有静态列的表插入数据和正常表类似,比如我们现在往 iteblog_users_with_status_updates 导入数据:

cqlsh:iteblog_keyspace> INSERT INTO "iteblog_users_with_status_updates"... ("username", "id", "email", "encrypted_password", "body")... VALUES (...   'iteblog',...   NOW(),...   'iteblog_hadoop@iteblog.com',...   0x877E8C36EFA827DBD4CAFBC92DD90D76,...   'Learning Cassandra!'... );
cqlsh:iteblog_keyspace> select username, email, encrypted_password, body from iteblog_users_with_status_updates;username | email                      | encrypted_password                 | body
----------+----------------------------+------------------------------------+---------------------iteblog | iteblog_hadoop@iteblog.com | 0x877e8c36efa827dbd4cafbc92dd90d76 | Learning Cassandra!(1 rows)

我们成功的插入一条数据了。但是上面的插入语句做了两件事:

  • 所有 username 为 iteblog 数据中的 email 和 encrypted_password 都被设置为 iteblog_hadoop@iteblog.com 和 0x877e8c36efa827dbd4cafbc92dd90d76 了。
  • 在 iteblog 所在的分区中新增了 body 内容为 Learning Cassandra! 的记录。
    现在我们再往表中插入一条数据,如下:
cqlsh:iteblog_keyspace> INSERT INTO "iteblog_users_with_status_updates"... ("username", "id", "body")... VALUES ('iteblog', NOW(), 'I love Cassandra!');
cqlsh:iteblog_keyspace> select username, email, encrypted_password, body from iteblog_users_with_status_updates;username | email                      | encrypted_password                 | body
----------+----------------------------+------------------------------------+---------------------iteblog | iteblog_hadoop@iteblog.com | 0x877e8c36efa827dbd4cafbc92dd90d76 | Learning Cassandra!iteblog | iteblog_hadoop@iteblog.com | 0x877e8c36efa827dbd4cafbc92dd90d76 |   I love Cassandra!(2 rows)
cqlsh:iteblog_keyspace>

可以看到,这次插入数据的时候,我们并没有指定 email 和 encrypted_password,但是从查询结果可以看出,新增加的行 email 和 encrypted_password 的值和之前是一样的!

现在由于某些原因,用户修改了自己的 email,我们来看看会发生什么事:

cqlsh:iteblog_keyspace> UPDATE iteblog_users_with_status_updates SET email = 'iteblog@iteblog.com'... WHERE username = 'iteblog';
cqlsh:iteblog_keyspace> select username, email, encrypted_password, body from iteblog_users_with_status_updates;username | email               | encrypted_password                 | body
----------+---------------------+------------------------------------+---------------------iteblog | iteblog@iteblog.com | 0x877e8c36efa827dbd4cafbc92dd90d76 | Learning Cassandra!iteblog | iteblog@iteblog.com | 0x877e8c36efa827dbd4cafbc92dd90d76 |   I love Cassandra!(2 rows)

从上面查询这输出的结果可以看出, username 为 iteblog 的 email 全部修改成一样的了!这就是静态列的强大之处。

现在表中存在了用户的邮箱和密码等信息,如果我们前端做了个页面支持用户修改自己的邮箱和密码,这时候我们的后台系统需要获取到现有的邮箱和密码,具体如下:

cqlsh:iteblog_keyspace> SELECT "username", "email", "encrypted_password"... FROM "iteblog_users_with_status_updates"... WHERE "username" = 'iteblog';username | email               | encrypted_password
----------+---------------------+------------------------------------iteblog | iteblog@iteblog.com | 0x877e8c36efa827dbd4cafbc92dd90d76iteblog | iteblog@iteblog.com | 0x877e8c36efa827dbd4cafbc92dd90d76(2 rows)

可以看出,表中有多少行 username 为 iteblog 的数据将会输出多少行邮箱和密码,这肯定不是我们想要的。这时候我们可以在查询的时候加上 DISTINCT 关键字,如下:

cqlsh:iteblog_keyspace> SELECT DISTINCT "username", "email", "encrypted_password"... FROM "iteblog_users_with_status_updates"... WHERE "username" = 'iteblog';username | email               | encrypted_password
----------+---------------------+------------------------------------iteblog | iteblog@iteblog.com | 0x877e8c36efa827dbd4cafbc92dd90d76(1 rows)

这样不管表中有多少行 username 为 iteblog 的数据,最终都会显示一行数据。注意,虽然我们加了 DISTINCT 关键字,但是 Cassandra 并不是将 username 为 iteblog 的数据全部拿出来,然后再去重的,因为静态列本来在底层就存储了一份,所以没必要去重。

静态列的意义

到这里,我们已经了解了 Cassandra 中静态列的创建、使用等。那静态列有什么意义呢?因为 Cassandra 中是不支持 join 的,静态列相当于把两张表进行了 join 操作。

那什么时候建议使用静态列呢?如果两张表关联度很大,而且我们经常需要同时查询这两张表,那这时候就可以考虑使用静态列了。


原文链接
本文为云栖社区原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/519078.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

android线性布局快捷键,【整理】Android图形界面知识学习与总结之:Linear Layout线性布局...

【背景】之前已经学习了:现在接着去学习:整理如下:Linear Layout1.LinearLayout是一个视图组合2.LinearLayout中的子视图只能已单个方向排列,要么是水平,要么是垂直;4.所有如果是垂直的列表,则每…

linux查看openssh和openssl版本命令

查看openssh版本命令 ssh -V查看openssl版本命令 openssl version

TensorFlow 2.0+Keras 防坑指南

TensorFlow 2.0是对1.x版本做了一次大的瘦身,Eager Execution默认开启,并且使用Keras作为默认高级API, 这些改进大大降低的TensorFlow使用难度。 本文主要记录了一次曲折的使用KerasTensorFlow2.0的BatchNormalization的踩坑经历&#xff0c…

收藏!企业数据安全防护5条建议

引言:数据安全对企业生存发展有着举足轻重的影响,数据资产的外泄、破坏都会导致企业无可挽回的经济损失和核心竞争力缺失,而往往绝大多数中小企业侧重的是业务的快速发展,忽略了数据安全重要性。近年来,企业由于自身的…

容器安全拾遗 - Rootless Container初探

近期Docker 19.03中发布了一个重要的特性 “Rootless Container支持”。趁着五一假期,快速验证一下。本文参考了Experimenting with Rootless Docker 一文的内容,并且补充了更多的细节和上手内容。 Rootless容器背景与架构 Docker和Kubernetes已经成为…

android 参数 attrs.xml,使用attrs.xml自定义属性

控件有很多属性,如android:id、android:layout_width、android:layout_height等,但是这些属性都是系统自带的属性。使用attrs.xml文件,可以自己定义属性。本文在Android自定义控件的基础上,用attrs.xml文件自己定义了属性。首先&a…

mybatis:在springboot中的配置

Mybatis 配置 使全局的映射器启用或禁用缓存。 mybatis.configuration.cache-enabledtrue全局启用或禁用延迟加载。当禁用时,所有关联对象都会即时加载。 mybatis.configuration.lazy-loading-enabledtrue当启用时,有延迟加载属性的对象在被调用时将会完…

直面PHP微服务架构挑战

在4月20日的阿里云栖开发者沙龙PHP技术专场上,云智慧Technical VP高驰涛为大家介绍了微服务的前世今生,分享了微服务架构实践中所面对的诸多挑战以及相应的应对策略。 本次直播视频精彩回顾,戳这里! 直播回顾:https://…

5亿整数的大文件,怎么排序 ?面试被问傻!

来源 | 程序员追风编辑 | Carol出品| CSDN云计算(ID:CSDNcloud)最近一家公司,面试官一上来,就问了我这么一个问题,我一脸懵逼,决定记录一下。问题给你1个文件bigdata,大小4663M&…

RabbitMQ 的延时队列和镜像队列原理与实战

在阿里云栖开发者沙龙PHP技术专场上,掌阅资深后端工程师、掘金小测《Redis深度历险》作者钱文品为大家介绍了RabbitMQ的延时队列和镜像队列的原理与实践,重点比较了RabbitMQ提供的消息可靠与不可靠模式,同时介绍了生产环境下如何使用RabbitMQ…

springboot 整合mybatisplus输出sql语句不输出结果集

mybatis-plus: # 日志配置 logging:level:#基础包com.ruoyi: debug#指定报的日志级别org.springframework: warnmybatis-plus:mapper-locations: classpath*:com/gblfy/**/mapping/*.xmlconfiguration: # log-impl: org.apache.ibatis.logging.stdout.StdOutImp…

深入浅出网络编程与Swoole内核

在阿里云PHP技术沙龙专场中,阿里云邀请到php-nsq作者,pecl、Swoole开发组成员吴振宇分享了Swoole进程模型的原理与Swoole协程实现的原理。并结合具体开发案例讲解了Swoole在网络编程中的应用。 本次直播视频精彩回顾,戳这里! 直播…

Spark大数据分布式机器学习处理实战 | 博文精选

作者| 数挖小飞飞编辑 | Carol出品| CSDN云计算(ID:CSDNcloud)Spark是一种大规模、快速计算的集群平台,本文试图通过学习Spark官网的实战演练笔记提升作者实操能力以及展现Spark的精彩之处。本文的参考配置为:Deepin 1…

shell脚本触发java程序传参数

eods.sh nohup java -cp "./xxx.war/WEB-INF/lib/*:./xxx.war/WEB-INF/classes" com.gblfy.datatrans.controller.OdsDeal $1> /app/ods/logs/ods.log &#无参 ./eods.sh #有参 ./eods.sh 2020-12-22public static void main(String args[]) {if (args.leng…

五四,阿里巴巴新青年了解下?

今天,橙子挖掘了几位程序员小哥的故事,他们是淘宝技术节上涌现出的“高手”。为了追求极致,代码也能成为一种艺术,看完之后也许你会对技术人有完全不同的认识。 1 伯灵:“技术作品代表我对技术的态度:解决…

android zxing 自动对焦,ZXing自动对焦问题

Pavel Bobkov..5我在Samsung Galaxy Grand 2(Android 4)上遇到了同样的问题,并且找到了一个解决方案。启动相机之前,我禁用了自动对焦功能。1-2秒后,我启用了它。我尝试了几种方法,并决定定期切换自动对焦功能。为了实现这一点&am…

多场景下的AI疫情防控“天网”:解读云边端联动下的全栈 AI 技术

在全民抗疫的特殊时期下,伴随着春运返潮,企业陆续复工,从重点防控的机场、火车站,到学校、企业、社区等密集型场所,都是不能忽视的地点。除了人工逐一测量体温排查外,我们还发现,在人员复杂、流…

Twitter 宣布抛弃 Mesos,全面转向Kubernetes

美国西部时间 5 月 2 日下午 7 点,Twitter 公司在旧金山总部举行了一次技术发布会兼 Meetup。会上,Twitter 计算平台(Twitter Computing Platform)产品与技术负责人 David McLaughlin 正式宣布,Twitter 的基础而设施将…

Guns整合log4j2

文章目录一、排除内置logback1. 删除logback.xml2. 排除内置的logback二、整合log4j22.1. 依赖log4j22.2. 配置文件中配置2.3. log4j2日志文件2.4. 效果图2.5. 输出要素Sringboot 开源框架默认logback日志框架,Guns开源项目也是用logback日志框架 一、排除内置logba…

蚂蚁金服生产级 Raft 算法库存储模块剖析 | SOFAJRaft 实现原理

前言 SOFAJRaft 是一个基于 Raft 一致性算法的生产级高性能 Java 实现,支持 MULTI-RAFT-GROUP,适用于高负载低延迟的场景。 SOFAJRaft 存储模块分为: Log 存储记录 Raft 配置变更和用户提交任务日志;Meta 存储即元信息存储记录…