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};
输入 DESCRIBE school 查看键空间的创建语句,代码:
DESCRIBE school;
连接Keyspace
语法
USE ;
编写完整的连接Keyspace语句,连接school 键空间
use school;
效果:
修改键空间
语法
ALTER KEYSPACE WITH
编写完整的修改键空间语句,修改school键空间,把副本因子 从1改为2
ALTER KEYSPACE school WITH replication = {'class':'SimpleStrategy', 'replication_factor' : 2};
验证
- 输入 DESCRIBE school 查看键空间的创建语句,代码:
DESCRIBE school;
效果:看到school 键空间的创建语句,可以看到replication_factor 值为2
删除键空间
语法
DROP KEYSPACE
完整删除键空间语句,删除school键空间
代码
DROP KEYSPACE school;
效果,使用DESCRIBE keyspaces ; 验证school键空间是否存在,可以看出school已经不存在
操作表、索引
注意:操作前,先把键空间school键空间创建,并使用school 键空间,代码
CREATE KEYSPACE school WITH replication = {'class':'SimpleStrategy', 'replication_factor' : 3};
use school;
查看键空间下所有表
代码
DESCRIBE TABLES;
当前键空间下没有任何表,效果
执行返回 empty
创建表
语法
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;
cassandra的索引(KEY)
上面创建student的时候,把id 设置为primary key
在Cassandra中的primary key是比较宏观概念,用于从表中取出数据。primary key可以由1个或多个column组合而成。
不要在以下情况使用索引:
- 这列的值很多的情况下,因为你相当于查询了一个很多条记录,得到一个很小的结果。
- 表中有couter类型的列
- 频繁更新和删除的列
- 在一个很大的分区中去查询一条记录的时候(也就是不指定分区主键的查询)
Cassandra的5种Key
- Primary Key 主键
- Partition Key 分区Key
- Composite Key 复合key
- Compound Key 复合Key
- 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 的颜色与其他列不一样,效果:
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)
);
Clustering Key
决定同一个分区内相同 Partition Key 数据的排序,默认为升序,可以在建表语句里面手动设置排序的方式
修改表结构
语法,可以添加列,删除列
- 添加列,语法
ALTER TABLE 【table name】 ADD 【new column】 datatype;
给student添加一个列email代码:
ALTER TABLE student ADD email text;
执行代码后,进行查询,查看效果:
- 删除列,语法
ALTER table name DROP columnname;
代码:
cqlsh:school> ALTER table student DROP email;
删除student的email列,并查询效果:
删除表
语法:
DROP TABLE
删除student,代码如下:
DROP TABLE testtab2;
执行删除代码,然后查询testtab2,报错:unconfigured table testtab2,说明testtab2已经被删除,效果:
清空表
表的所有行都将永久删除
语法
TRUNCATE
代码
TRUNCATE student;
创建索引
普通列创建索引
语法
CREATE INDEX ON
代码
为student的 name 添加索引,索引的名字为:sname, 代码:
CREATE INDEX sname ON student (name);
为student 的age添加索引,不设置索引名字,代码
CREATE INDEX ON student (age);
执行上面的命令,然后使用 DESCRIBE student 查看表,效果:
可以发现 对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结合添加索引
效果:
删除索引
语法
DROP INDEX
删除student的sname 索引,代码
drop index sname;
执行上面代码,然后使用DESCRIBE student 查看表,发现sname索引已经不存在,效果:
添加数据
语法:
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 ,效果:
添加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;
查询数据
语法
使用 SELECT 、WHERE、LIKE、GROUP BY 、ORDER BY等关键词
SELECT FROM
SELECT FROM WHERE ;
根据主键查询
查询student_id = 1012 的行
代码
select * from student where id=1012;
效果:

查询时使用索引
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;
效果

对key_one 进行范围查询使用 > 号,无法查出结果:
select * from testtab where key_one>4;

第二主键 支持 = 、>、 <、 >= 、 <=
key_two是第二主键
不要单独对key_two 进行 查询,
代码:
select * from testtab where key_two = 8;
结果报错:

意思是如果想要完成这个查询,可以使用 ALLOW FILTERING
修改:
select * from testtab where key_two = 8 ALLOW FILTERING;

注意:加上ALLOW FILTERING 后确实可以查询出数据,但是不建议这么做
正确的做法是 ,在查询第二主键时,前面先写上第一主键
代码:
select * from testtab where key_one=12 and key_two = 8 ;
效果:

普通列,非索引非主键字段
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; --可以查询
效果:

集合列
使用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值
效果:

ALLOW FILTERING
ALLOW FILTERING是一种非常消耗计算机资源的查询方式。
如果表包含例如100万行,并且其中95%具有满足查询条件的值,则查询仍然相对有效,这时应该使用ALLOW FILTERING。
如果表包含100万行,并且只有2行包含满足查询条件值,则查询效率极低。Cassandra将无需加载999,998行。如果经常使用查询,则最好在列上添加索引。
ALLOW FILTERING在表数据量小的时候没有什么问题,但是数据量过大就会使查询变得缓慢。
查询时排序
cassandra也是支持排序的,order by。 排序也是有条件的
- 必须有第一主键的=号查询 cassandra的第一主键是决定记录分布在哪台机器上,cassandra只支持单台机器上的记录排序。
- 只能根据第二、三、四…主键进行有序的,相同的排序。
- 不能有索引查询 ,cassandra的任何查询,最后的结果都是有序的,内部就是这样存储的。索引列 支持 like ,主键支持 group by
分页查询
使用limit 关键字来限制查询结果的条数 进行分页
更新列数据
更新表中的数据,可用关键字:
- Where - 选择要更新的行
- Set - 设置要更新的值
- Must - 包括组成主键的所有列
在更新行时,如果给定行不可用,则UPDATE创建一个新行
语法:
UPDATE
SET =
= ....
WHERE
更新简单数据
把id = 1012 的数据的gender列 的值改为1,代码:
UPDATE student set gender = 1 where id= 1012;

更新set类型数据
在student中interest列是set类型
添加一个元素
使用UPDATE命令 和 ‘+’ 操作符
代码:
UPDATE student SET interest = interest + {'游戏'} WHERE id = 1012;
先查询,执行上面的代码,再查询,效果:

删除一个元素
使用UPDATE命令 和 ‘-’ 操作符
代码:
UPDATE student SET interest = interest - {'电影'} WHERE id = 1012;
效果:

删除所有元素
可以使用UPDATA或DELETE命令,效果一样
代码:
UPDATE student SET interest = {} WHERE id = 1012;
或
DELETE interest FROM student WHERE id = 1012;
效果:

一般来说,Set,list和Map要求最少有一个元素,否则Cassandra无法把其同一个空值区分
更新list类型数据
在student中phone列是list类型
使用UPDATA命令向list插入值
代码:
UPDATE student SET phone = ['020-777777777', '13666666666'] WHERE id = 1012;

在list前面插入值
代码:
UPDATE student SET phone = [ '030-55555555' ] + phone WHERE id = 1012;
可以看到新数据的位置在旧数据的前面,效果:

在list后面插入值
代码:
UPDATE student SET phone = phone + [ '040-33333333' ] WHERE id = 1012;
可以看到新数据的位置在最后面,效果:

使用列表索引设置值,覆盖已经存在的值
这种操作会读入整个list,效率比上面2种方式差
现在把phone中下标为3的数据,也就是 “040-33333333”替换,代码:
UPDATE student SET phone[3] = '050-22222222' WHERE id = 1012;
效果:

【不推荐】使用DELETE命令和索引删除某个特定位置的值
非线程安全的,如果在操作时其它线程在前面添加了一个元素,会导致移除错误的元素
代码:
DELETE phone[2] FROM student WHERE id = 1012;
效果:

【推荐】使用UPDATE命令和‘-’移除list中所有的特定值
代码:
UPDATE student SET phone = phone - ['020-777777777'] WHERE id = 1012;
效果:

更新map类型数据
map输出顺序取决于map类型。
使用Insert或Update命令
UPDATE student SET education=
{'中学': '城市第五中学', '大学': '城市第五大学'} WHERE id = 1012;

使用UPDATE命令设置指定元素的value
UPDATE student SET education['中学'] = '爱民中学' WHERE id = 1012;

增加map元素
可以使用如下语法增加map元素。如果key已存在,value会被覆盖,不存在则插入
UPDATE student SET education = education + { '幼儿园' : '大海幼儿园', '中学': '科技路中学'} WHERE id = 1012;

删除元素
可以用DELETE 和 UPDATE 删除Map类型中的数据
使用DELETE删除数据
DELETE education['幼儿园'] FROM student WHERE id = 1012;

使用UPDATE删除数据
UPDATE student SET education=education - {'中学','大学'} WHERE id = 1012;

删除行
语法
DELETE FROM WHERE ;
代码
删除student中id=1012 的数据,代码:
DELETE FROM student WHERE id=1012;
效果:

批量操作
作用
把多次更新操作(不能执行查询操作)合并为一次请求,减少客户端和服务端的网络交互。 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;
效果:
