Cassandra:cql基本操作


操作键空间

创建Keyspace

语法

CREATE KEYSPACE  WITH ;

更具体的语法:

Create keyspace KeyspaceName with replicaton={'class':strategy name,   
'replication_factor': No of replications on different nodes};

要填写的内容:

KeyspaceName 代表键空间的名字

strategy name 代表副本放置策略,内容包括:简单策略、网络拓扑策略,选择其中的一个。

No of replications on different nodes 代表 复制因子,放置在不同节点上的数据的副本数。

编写完成的创建语句

创建一个键空间名字为:school,副本策略选择:简单策略 SimpleStrategy,副本因子:1

CREATE KEYSPACE school WITH replication = {'class':'SimpleStrategy', 'replication_factor' : 1};

image-20220315164751673

输入 DESCRIBE school 查看键空间的创建语句,代码:

DESCRIBE school;

image-20220315164832739

连接Keyspace

语法

USE ;

编写完整的连接Keyspace语句,连接school 键空间

use school;

效果:

image-20220315165137748

修改键空间

语法

ALTER KEYSPACE  WITH 

编写完整的修改键空间语句,修改school键空间,把副本因子 从1改为2

ALTER KEYSPACE school WITH replication = {'class':'SimpleStrategy', 'replication_factor' : 2};

验证

  • 输入 DESCRIBE school 查看键空间的创建语句,代码:
DESCRIBE school;

效果:看到school 键空间的创建语句,可以看到replication_factor 值为2

image-20220315165249366

删除键空间

语法

DROP KEYSPACE 

完整删除键空间语句,删除school键空间

代码

DROP KEYSPACE school;

效果,使用DESCRIBE keyspaces ; 验证school键空间是否存在,可以看出school已经不存在

image-20220315165356334

操作表、索引

注意:操作前,先把键空间school键空间创建,并使用school 键空间,代码

CREATE KEYSPACE school WITH replication = {'class':'SimpleStrategy', 'replication_factor' : 3};
use school;

查看键空间下所有表

代码

 DESCRIBE TABLES;

当前键空间下没有任何表,效果

执行返回 empty

image-20220315165521545

创建表

语法

CREATE (TABLE | COLUMNFAMILY)  ('' , '')
(WITH 

完整创建表语句,创建student 表,student包含属性如下:

学生编号(id), 姓名(name),年龄(age),性别(gender),家庭地址(address),interest(兴趣),phone(电话号码),education(教育经历)

id 为主键,并且为每个Column选择对应的数据类型。

注意:interest 的数据类型是set ,phone的数据类型是list,education 的数据类型是map

CREATE TABLE student(
   id int PRIMARY KEY,  
   name text,  
   age int,  
   gender tinyint,  
   address text ,
   interest set,
   phone list,
   education map
);

验证

  • 使用 DESCRIBE TABLE student; 查看创建的表
cqlsh:school> DESCRIBE TABLE student;

image-20220315165857082

cassandra的索引(KEY)

上面创建student的时候,把id 设置为primary key

在Cassandra中的primary key是比较宏观概念,用于从表中取出数据。primary key可以由1个或多个column组合而成。

不要在以下情况使用索引:

  • 这列的值很多的情况下,因为你相当于查询了一个很多条记录,得到一个很小的结果。
  • 表中有couter类型的列
  • 频繁更新和删除的列
  • 在一个很大的分区中去查询一条记录的时候(也就是不指定分区主键的查询)
Cassandra的5种Key
  1. Primary Key 主键
  2. Partition Key 分区Key
  3. Composite Key 复合key
  4. Compound Key 复合Key
  5. Clustering Key 集群
Primary Key

是用来获取某一行的数据, 可以是单一列(Single column Primary Key)或者多列(Composite Primary Key)。

在 Single column Primary Key 决定这一条记录放在哪个节点。

例如:

create table testTab (
id int PRIMARY KEY,
name text
);
Composite Primary Key

如果 Primary Key 由多列组成,那么这种情况称为 Compound Primary Key 或 Composite Primary Key。

例如:

create table testTab (
key_one int,
key_two int,
name text,
PRIMARY KEY(key_one, key_two)
);

执行创建表后,查询testTab,会发现key_one和key_two 的颜色与其他列不一样,效果:

image-20220315171055611

Partition Key

在组合主键的情况下(上面的例子),第一部分称作Partition Key(key_one就是partition key),第二部分是CLUSTERING KEY(key_two)

Cassandra会对Partition key 做一个hash计算,并自己决定将这一条记录放在哪个节点。

如果 Partition key 由多个字段组成,称之为 Composite Partition key

例如:

create table testTab2 (
key_part_one int,
key_part_two int,
key_clust_one int,
key_clust_two int,
key_clust_three uuid,
name text,
PRIMARY KEY((key_part_one,key_part_two), key_clust_one, key_clust_two, key_clust_three)
);

image-20220315171441295

Clustering Key

决定同一个分区内相同 Partition Key 数据的排序,默认为升序,可以在建表语句里面手动设置排序的方式

修改表结构

语法,可以添加列,删除列

  • 添加列,语法
ALTER TABLE 【table name】 ADD  【new column】 datatype;

给student添加一个列email代码:

ALTER TABLE student ADD email text;

执行代码后,进行查询,查看效果:

image-20220315171553250

  • 删除列,语法
ALTER table name DROP columnname;

代码:

cqlsh:school> ALTER table student DROP email;

删除student的email列,并查询效果:

image-20220315171646238

删除表

语法:

DROP TABLE 

删除student,代码如下:

DROP TABLE testtab2;

执行删除代码,然后查询testtab2,报错:unconfigured table testtab2,说明testtab2已经被删除,效果:

image-20220315171736038

清空表

表的所有行都将永久删除

语法

TRUNCATE 

代码

TRUNCATE student;

创建索引

普通列创建索引

语法

CREATE INDEX  ON 

代码

为student的 name 添加索引,索引的名字为:sname, 代码:

CREATE INDEX sname ON student (name);

为student 的age添加索引,不设置索引名字,代码

CREATE INDEX ON student (age);

执行上面的命令,然后使用 DESCRIBE student 查看表,效果:

image-20220315172105686

可以发现 对age创建索引,没有指定索引名字,会提供一个默认的索引名:student_age_idx。

索引原理:

Cassandra之中的索引的实现相对MySQL的索引来说就要简单粗暴很多了。Cassandra自动新创建了一张表格,同时将原始表格之中的索引字段作为新索引表的Primary Key!并且存储的值为原始数据的Primary Key .

集合列创建索引

给集合列设置索引

CREATE INDEX ON student(interest);                 -- set集合添加索引
CREATE INDEX mymap ON student(KEYS(education));          -- map结合添加索引

效果:

image-20220315172503987

删除索引

语法

DROP INDEX 

删除student的sname 索引,代码

drop index sname;

执行上面代码,然后使用DESCRIBE student 查看表,发现sname索引已经不存在,效果:

image-20220315172954012

添加数据

语法:

INSERT INTO (, ....) VALUES (, ....) USING 

给student添加2行数据,包含对set,list ,map类型数据,代码:

set类型用大括号

list类型用中括号

map类似于json格式

INSERT INTO student (id,address,age,gender,name,interest, phone,education) VALUES (1011,'中山路21号',16,1,'Tom',{'游泳', '跑步'},['010-88888888','13888888888'],{'小学' : '城市第一小学', '中学' : '城市第一中学'}) ;

INSERT INTO student (id,address,age,gender,name,interest, phone,education) VALUES (1012,'朝阳路19号',17,2,'Jerry',{'看书', '电影'},['020-66666666','13666666666'],{'小学' :'城市第五小学','中学':'城市第五中学'});

执行上面的代码,然后 select * from student ,效果:

image-20220315173214406

添加TTL,设定的computed_ttl数值秒后,数据会自动删除:

INSERT INTO student (id,address,age,gender,name,interest, phone,education) VALUES (1030,'朝阳路30号',20,1,'Cary',{'运动', '游戏'},['020-7777888','139876667556'],{'小学' :'第30小学','中学':'第30中学'}) USING TTL 60;

image-20220315173703865

查询数据

语法

使用 SELECT 、WHERE、LIKE、GROUP BY 、ORDER BY等关键词

SELECT FROM 
SELECT FROM  WHERE ;

根据主键查询

查询student_id = 1012 的行

代码

select * from student where id=1012;

效果:

image-20220315174048641

查询时使用索引

Cassandra对查询时使用索引有一定的要求,具体如下:

  • Primary Key 只能用 = 号查询
  • 第二主键 支持= > < >= <=
  • 索引列 只支持 = 号
  • 非索引非主键字段过滤可以使用ALLOW FILTERING
create table testTab (
key_one int,
key_two int,
name text
PRIMARY KEY(key_one, key_two)
);

INSERT INTO "school"."testtab" ("key_one","key_two","name") VALUES (16,13,'john');
INSERT INTO "school"."testtab" ("key_one","key_two","name") VALUES (8,5,'tom');
INSERT INTO "school"."testtab" ("key_one","key_two","name") VALUES (4,2,'jack');
INSERT INTO "school"."testtab" ("key_one","key_two","name") VALUES (12,8,'jerry');

key_one列是第一主键

对key_one进行 = 号查询,可以查出结果

代码如下

select * from testtab where key_one=4;

效果

image-20220315174739949

对key_one 进行范围查询使用 > 号,无法查出结果:

select * from testtab where key_one>4;

image-20220315174804300

第二主键 支持 = 、>、 <、 >= 、 <=

key_two是第二主键

不要单独对key_two 进行 查询,

代码:

select * from testtab where key_two = 8;

结果报错:

image-20220315174940309

意思是如果想要完成这个查询,可以使用 ALLOW FILTERING

修改:

select * from testtab where key_two = 8 ALLOW FILTERING;

image-20220315175016256

注意:加上ALLOW FILTERING 后确实可以查询出数据,但是不建议这么做

正确的做法是 ,在查询第二主键时,前面先写上第一主键

代码:

select * from testtab where key_one=12 and key_two = 8 ;

效果:

image-20220315175047631

普通列,非索引非主键字段

name是普通列,在查询时需要使用ALLOW FILTERING。

代码:

select * from testtab where key_one=12 and name='jerry'; --报错
select * from testtab where key_one=12 and name='jerry' allow filtering;  --可以查询

效果:

image-20220315175215459

集合列

使用student表来测试集合列上的索引使用。

假设已经给集合添加了索引,就可以使用where子句的CONTAINS条件按照给定的值进行过滤。

select * from student where interest CONTAINS '电影';        -- 查询set集合
select * from student where education CONTAINS key  '小学';  --查询map集合的key值
select * from student where education CONTAINS '中心第9小学' allow filtering; --查询map的value值

效果:

image-20220315175649779

ALLOW FILTERING

ALLOW FILTERING是一种非常消耗计算机资源的查询方式。
如果表包含例如100万行,并且其中95%具有满足查询条件的值,则查询仍然相对有效,这时应该使用ALLOW FILTERING。

如果表包含100万行,并且只有2行包含满足查询条件值,则查询效率极低。Cassandra将无需加载999,998行。如果经常使用查询,则最好在列上添加索引。

ALLOW FILTERING在表数据量小的时候没有什么问题,但是数据量过大就会使查询变得缓慢。

查询时排序

cassandra也是支持排序的,order by。 排序也是有条件的

  1. 必须有第一主键的=号查询 cassandra的第一主键是决定记录分布在哪台机器上,cassandra只支持单台机器上的记录排序。
  2. 只能根据第二、三、四…主键进行有序的,相同的排序。
  3. 不能有索引查询 ,cassandra的任何查询,最后的结果都是有序的,内部就是这样存储的。索引列 支持 like ,主键支持 group by

分页查询

使用limit 关键字来限制查询结果的条数 进行分页

更新列数据

更新表中的数据,可用关键字:

  • Where - 选择要更新的行
  • Set - 设置要更新的值
  • Must - 包括组成主键的所有列

在更新行时,如果给定行不可用,则UPDATE创建一个新行

语法:

UPDATE 
SET  = 
 = ....
WHERE 

更新简单数据

把id = 1012 的数据的gender列 的值改为1,代码:

UPDATE student set gender = 1 where id= 1012;

image-20220316144005786

更新set类型数据

在student中interest列是set类型

添加一个元素

使用UPDATE命令 和 ‘+’ 操作符

代码:

UPDATE student SET interest = interest + {'游戏'} WHERE id = 1012;

先查询,执行上面的代码,再查询,效果:

image-20220316144123609

删除一个元素

使用UPDATE命令 和 ‘-’ 操作符

代码:

UPDATE student SET interest = interest - {'电影'} WHERE id = 1012;

效果:

image-20220316144203772

删除所有元素

可以使用UPDATA或DELETE命令,效果一样

代码:

UPDATE student SET interest = {} WHERE id = 1012;
或
DELETE interest FROM student WHERE id = 1012;

效果:

image-20220316144305640

一般来说,Set,list和Map要求最少有一个元素,否则Cassandra无法把其同一个空值区分

更新list类型数据

在student中phone列是list类型

使用UPDATA命令向list插入值

代码:

UPDATE student SET phone = ['020-777777777', '13666666666'] WHERE id = 1012;

image-20220316144511119

在list前面插入值

代码:

UPDATE student SET phone = [ '030-55555555' ] + phone WHERE id = 1012;

可以看到新数据的位置在旧数据的前面,效果:

image-20220316144527311

在list后面插入值

代码:

UPDATE student SET phone = phone + [ '040-33333333' ]  WHERE id = 1012;

可以看到新数据的位置在最后面,效果:

image-20220316144557291

使用列表索引设置值,覆盖已经存在的值

这种操作会读入整个list,效率比上面2种方式差

现在把phone中下标为3的数据,也就是 “040-33333333”替换,代码:

UPDATE student SET phone[3] = '050-22222222' WHERE id = 1012;

效果:

image-20220316144700785

【不推荐】使用DELETE命令和索引删除某个特定位置的值

非线程安全的,如果在操作时其它线程在前面添加了一个元素,会导致移除错误的元素

代码:

DELETE phone[2] FROM student WHERE id = 1012;

效果:

image-20220316144733546

【推荐】使用UPDATE命令和‘-’移除list中所有的特定值

代码:

UPDATE student SET phone = phone - ['020-777777777'] WHERE id = 1012;

效果:

image-20220316144814931

更新map类型数据

map输出顺序取决于map类型。

使用Insert或Update命令

UPDATE student SET education=
  {'中学': '城市第五中学', '大学': '城市第五大学'} WHERE id = 1012;

image-20220316144927914

使用UPDATE命令设置指定元素的value

UPDATE student SET education['中学'] = '爱民中学' WHERE id = 1012;

image-20220316145007559

增加map元素

可以使用如下语法增加map元素。如果key已存在,value会被覆盖,不存在则插入

UPDATE student SET education = education + { '幼儿园' : '大海幼儿园', '中学': '科技路中学'} WHERE id = 1012;

image-20220316145115848

删除元素

可以用DELETE 和 UPDATE 删除Map类型中的数据

使用DELETE删除数据

DELETE education['幼儿园'] FROM student WHERE id = 1012;

image-20220316145153521

使用UPDATE删除数据

UPDATE student SET education=education - {'中学','大学'} WHERE id = 1012;

image-20220316145225733

删除行

语法

DELETE FROM  WHERE ;

代码

删除student中id=1012 的数据,代码:

DELETE FROM student WHERE id=1012;

效果:

image-20220316145317304

批量操作

作用

把多次更新操作(不能执行查询操作)合并为一次请求,减少客户端和服务端的网络交互。 batch中同一个partition key的操作具有隔离性

语法

使用BATCH,您可以同时执行多个修改语句(插入,更新,删除)

BEGIN BATCH
/ / 
APPLY BATCH

代码

BEGIN BATCH
	INSERT INTO student (id,address,age,gender,name) VALUES (1015,'上海路',20,1,'Jack') ;
	UPDATE student set age = 11 where id= 1011;
APPLY BATCH;

效果:

image-20220316145526422