CQL(Cassandra Query Language)数据定义,cqlcassandra
CQL将数据存储在表中,这些表的模式定义了表中所述数据的布局,这些表被分组在键空间中。 键空间定义了一些适用于其包含的所有表的选项,其中最显着的是键空间使用的复制策略。 通常鼓励应用程序使用一个键空间,因此许多集群可以仅定义一个键空间。 本节介绍用于创建,修改和删除这些键空间和表的语句。1.常规定义 键空间和表的名称由以下语法定义:
keyspace_name ::=键空间和表名都应该只包含字母数字字符,不能为空,并且大小限制为48个字符(该限制主要用于避免文件名(可能包括键空间和表名)超过某些文件的系统限制)。默认情况下,键空间和表名称不区分大小写(myTable等效于mytable),但是可以通过使用双引号强制区分大小写(“myTable”与mytable不同)。 表始终是键空间的一部分,并且表名称可以由其所属的键空间完全限定。 如果不是完全限定的,则假定表位于当前键空间中。 此外,列的有效名称简单定义为:nametable_name ::= [keyspace_name'.' ]namename ::=unquoted_name|quoted_nameunquoted_name ::= re('[a-zA-Z_0-9]{1, 48}') quoted_name ::= '"'unquoted_name'"'
column_name ::= identifier
我们还定义语句选项的概念,以在以下部分中使用:
options ::=option( ANDoption)* option ::=identifier'=' (identifier|constant|map_literal)
2.创建键空间 使用CREATE KEYSPACE语句创建键空间:
create_keyspace_statement ::= CREATE KEYSPACE [ IF NOT EXISTS ]示例:keyspace_nameWITHoptions
CREATE KEYSPACE Excelsior WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 3}; CREATE KEYSPACE Excalibur WITH replication = {'class': 'NetworkTopologyStrategy', 'DC1' : 1, 'DC2' : 3} AND durable_writes = false;支持的选项有:
| 名称 | 类型 | 强制性 | 默认值 | 描述 |
|---|---|---|---|---|
replication |
map | yes | 复制策略和用于键空间的选项 | |
durable_writes |
simple | no | true | 是否使用提交日志来更新此键空间 |
- 'SimpleStrategy':定义整个集群的复制因子的简单策略。 支持的唯一子选项是'replication_factor'以定义该复制因子并且是必需的。
- 'NetworkTopologyStrategy':允许为每个数据中心独立设置复制因素的复制策略。 其余的子选项是键值对,其中键是数据中心名称,其值是关联的复制因子。
3.使用空间 USE语句允许更改当前键空间。 CQL中有多个对象绑定到键空间,如表,用户定义的类型,函数等并且这些对象使用的默认键空间是当前键空间,没有完全限定名称(即前面没有一个键空间名称)。 使用USE语句只需要将键空间用作当前参数值:
use_statement ::= USE keyspace_name
alter_keyspace_statement ::= ALTER KEYSPACE示例:keyspace_nameWITHoptions
ALTER KEYSPACE Excelsior WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 4};支持的选项与创建键空间相同。
drop_keyspace_statement ::= DROP KEYSPACE [ IF EXISTS ] keyspace_name
示例:
DROP KEYSPACE Excelsior;删除键空间立即地、不可逆地,删除包括其中的所有表,UTD和函数以及这些表中包含的所有数据。 如果键空间不存在,则语句将返回错误,除非使用IF EXISTS,在这种情况下操作是无操作。
6.创建表 创建新表使用CREATE TABLE语句:
create_table_statement ::= CREATE TABLE [ IF NOT EXISTS ]示例:table_name'('column_definition( ','column_definition)* [ ',' PRIMARY KEY '('primary_key')' ] ')' [ WITHtable_options] column_definition ::=column_namecql_type[ STATIC ] [ PRIMARY KEY] primary_key ::=partition_key[ ','clustering_columns] partition_key ::=column_name| '('column_name( ','column_name)* ')' clustering_columns ::=column_name( ','column_name)* table_options ::= COMPACT STORAGE [ ANDtable_options] | CLUSTERING ORDER BY '('clustering_order')' [ ANDtable_options] |optionsclustering_order ::=column_name(ASC | DESC) ( ','column_name(ASC | DESC) )*
CREATE TABLE monkeySpecies ( species text PRIMARY KEY, common_name text, population varint, average_size int ) WITH comment='Important biological records' AND read_repair_chance = 1.0; CREATE TABLE timeline ( userid uuid, posted_month int, posted_time uuid, body text, posted_by text, PRIMARY KEY (userid, posted_month, posted_time) ) WITH compaction = { 'class' : 'LeveledCompactionStrategy' }; CREATE TABLE loads ( machine inet, cpu int, mtime timeuuid, load float, PRIMARY KEY ((machine, cpu), mtime) ) WITH CLUSTERING ORDER BY (mtime DESC);
CQL表具有名称,并由一组行组成。创建表等于定义将哪些列组成行,哪些列组成主键,以及表的可选选项。
尝试创建已存在的表将返回错误,除非使用IF NOT EXISTS指令。如果使用它,如果表已经存在,语句将是一个无操作。
6-1.列定义
CQL表中的每一行都有一组在创建表时定义的预定义列(或稍后使用alter语句添加)。
列的定义主要由列的名称和列的类型组成,它限制该列接受哪些值。此外,列定义可以具有以下修饰符:
STATIC:它将该列声明为静态列。PRIMARYKEY:它声明该列是表的主键的唯一组件。
6-2.静态列
在表定义中,一些列可以声明为STATIC。属于静态的列将由属于同一分区(具有相同的分区键)的所有行“共享”。例如:
CREATE TABLE t ( pk int, t int, v text, s text static, PRIMARY KEY (pk, t) ); INSERT INTO t (pk, t, v, s) VALUES (0, 0, 'val0', 'static0'); INSERT INTO t (pk, t, v, s) VALUES (0, 1, 'val1', 'static1'); SELECT * FROM t; pk | t | v | s ----+---+--------+----------- 0 | 0 | 'val0' | 'static1' 0 | 1 | 'val1' | 'static1'可以看出,对于分区中的行(该示例中的分区键是pk,两行都在同一分区中)的s值是相同的(static1):第二插入覆盖了s的值。
使用静态列的限制如下:
- 具有COMPACT STORAGE选项(见下文)的表不能使用它们;
- 没有聚簇列的表不能有静态列(在没有聚簇列的表中,每个分区只有一行,因此每列都是固有的);
- 只有非PRIMARY KEY列可以是静态的。
6-3.Primary key
在表中,一行由其PRIMARY KEY唯一标识,因此所有表必须定义一个PRIMARY KEY(只有一个)。PRIMARY KEY的定义由表中的一个或多个列组成。在语法上,主键定义了关键字PRIMARY KEY,后跟逗号分隔的在括号中组成它的列名的列表,但是如果主键只有一列,则可以通过PRIMARY KEY关键字替代该列定义。主键定义中的列顺序很重要。
CQL主键由2部分组成:
-
分区键部分。 它是主键定义的第一个组件。它可以是单个列,可以是多个列。一个表总是至少有一个分区键,最小的可能表定义是:
CREATE TABLE t (k text PRIMARY KEY);
-
聚簇列。这些是主键定义的第一个组件之后的列,这些列的顺序定义了聚簇顺序。
主键定义的一些示例:
PRIMARY KEY (a):a是分区键,并且没有聚簇列。PRIMARY KEY (a, b, c):a是分区键,并且b和c是聚簇列。PRIMARY KEY ((a, b), c): a和b组成分区键(这通常称为复合分区键),c是聚类列。
6-4.分区键
在表中,CQL定义了分区的概念。 分区只是它们的分区键具有相同值的一组行。注意,如果分区键由多个列组成,那么行属于同一分区,只有它们对所有这些分区键列具有相同的值。例如,给定下面的表定义和内容:
CREATE TABLE t ( a int, b int, c int, d int, PRIMARY KEY ((a, b), c, d) ); SELECT * FROM t; a | b | c | d ---+---+---+--- 0 | 0 | 0 | 0 // row 1 0 | 0 | 1 | 1 // row 2 0 | 1 | 2 | 2 // row 3 0 | 1 | 3 | 3 // row 4 1 | 1 | 4 | 4 // row 5
第1行和第2行在同一个分区中,第3行和第4行也在同一个分区中(但是不同的一个),而第5行在另一个分区中。
注意,表始终具有分区键,并且如果表没有聚簇列,则该表的每个分区仅由单个行组成(因为主键唯一地标识行,并且主键等于分区键如果没有聚簇列)。
分区的最重要的属性是属于同一分区的所有行保证被存储在同一副本节点集合上。换句话说,表的分区键定义了哪些行将在集群中一起本地化,因此重要的是明智地选择分区键,以便需要一起提取的行在同一个分区中(因此一起查询这些行需要联系最少的节点)。
这种保证还有另一个方面:因为共享一个分区键的所有行都保证存储在同一副本节点集合上,分组太多数据的分区键可以创建一个热点。分区的另一个有用的属性是,当写入数据时,属于单个分区的所有更新是原子地并且隔离地完成的,而跨分区不是这样。
正确选择表的分区键和聚簇列可能是Cassandra中数据建模最重要的方面之一,它在很大程度上影响可以执行的查询以及它们的效率。
6-5.聚簇列
表的聚簇列定义了该表的分区的聚类顺序。 对于给定的分区,所有行在Cassandra内通过该聚类顺序物理排序。例如,给定:
CREATE TABLE t ( a int, b int, c int, PRIMARY KEY (a, b, c) ); SELECT * FROM t; a | b | c ---+---+--- 0 | 0 | 4 // row 1 0 | 1 | 9 // row 2 0 | 2 | 2 // row 3 0 | 3 | 3 // row 4
那么所有行(它们都属于同一分区)全部以它们的b列的值的顺序(它们在上面显示的顺序)在内部存储。因此,表的分区键允许对同一副本集上的行进行分组时,聚簇列控制这些行如何存储在副本上。该排序允许检索分区内的一定范围的行(例如,在上面的示例中,SELECT * FROM t WHERE a = 0 AND b> 1 AND b <= 3)非常有效。
6-6.表选项
CQL表具有可在创建时设置的多个选项(对于大多数选项可以在之后进行更改)。这些选项在WITH关键字后指定。
在这些选项中,两个重要的选项在创建后不能更改,并影响可以对表执行哪些查询:COMPACT STORAGE选项和CLUSTERING ORDER选项。这两个选项以及表的其他选项在以下部分中描述。
6-7.紧凑表
警告:从Cassandra 3.0开始,紧凑表在内部具有与非紧凑表相同的布局(对于相同的模式),并且为了确保与已弃用的ThriftAPI向后兼容声明表紧凑只会对表定义和使用造成人为限制。但是COMPACT STORAGE不能兼容,Cassandra 4.0之后将被删除,所以强烈建议不要使用COMPACT STORAGE选项创建新表。
紧凑表是使用COMPACT STORAGE选项定义的表。 此选项主要针对在CQL版本3之前创建的定义的向后兼容性(有关更多详细信息,请参阅www.datastax.com/dev/blog/thrift-to-cql3),不应将其用于新表。使用此选项声明表会对表创建限制,这些限制在很大程度上是任意的,但对于与(不推荐的)Thrift API的向后兼容性是必需的。紧凑表中限制:- 紧凑表不能使用集合或静态列。
- 如果紧凑表具有至少一个聚类列,则它必须在主键之外具有正好一个列。这意味着您不能在创建后特别添加或删除列。
- 紧凑表在其可以创建的索引中受到限制,并且不能在其上创建实体化视图
6-8.反转聚簇顺序
表的聚簇顺序由该表的聚类列定义。 默认情况下,该排序基于这些聚簇顺序的自然顺序,但是CLUSTERING ORDER允许更改该聚类顺序以对某些(可能全部)列使用反向自然顺序。
CLUSTERING ORDER选项采用聚类列的逗号分隔列表,每个列都有一个ASC(升序)或DESC(降序)。特别要注意的是,默认值(如果不使用CLUSTERING ORDER选项)严格等同于使用ASC修改器在所有聚簇列中使用该选项。
请注意,此选项基本上是存储引擎更改存储行的顺序的提示,但它有3个可见的后果:
- #它限制允许在该表上进行选择的ORDER BY子句。你只能按照聚簇顺序或反向聚簇顺序排序结果。这意味着如果表具有2个聚类列a和b,并且您定义了WITH CLUSTERING ORDER(DESC,b ASC),那么在查询中,您将被允许使用ORDER BY(DESC,b ASC)和(反向聚类顺序)ORDER BY(ASC,b DESC),但不是ORDER BY(ASC,b ASC)(也不是ORDER BY(DESC,b DESC))。
- # 它也会更改查询时的结果的默认顺序(如果没有提供ORDER BY)。始终返回结果(在分区内)。
- # 它对一些查询具有小的性能影响,因为反向聚类顺序中的查询比正向聚类顺序中的查询慢。在实践中,这意味着如果你计划大部分按照列的反向自然顺序进行查询(这在时间序列中很常见,例如你经常想要数据从最新到最旧),那么它是一种优化。
6-9.其它表选项
表支持以下选项:
| 选项 | 类型 | 默认值 | 描述 |
|---|---|---|---|
comment |
simple | none | 表字段的注释 |
read_repair_chance |
simple | 0.1 | 为了读修复的目的查询额外节点(例如,比一致性级别所需的更多节点)的概率。 |
dclocal_read_repair_chance |
simple | 0 | 为了读修复的目的,查询属于与读协调器相同的数据中心的额外节点(例如,比一致性级别所需的更多节点)的概率。 |
gc_grace_seconds |
simple | 864000 | 在垃圾收集标记删除标记之前等待的时间。 |
bloom_filter_fp_chance |
simple | 0.00075 | sstables bloom过滤器的假阳性的目标概率。 所述bloom过滤器将被调整大小以提供所提供的概率(因此降低该值影响存储器和磁盘中的bloom过滤器的大小) |
default_time_to_live |
simple | 0 | 表的默认到期时间(“TTL”)(以秒为单位)。 |
compaction |
map | 见下文 | 见下文 |
compression |
map | 见下文 | 见下文 |
caching |
map | 见下文 | 见下文 |
Compaction options
压缩选项必须至少定义“class”子选项,该选项定义要使用的压缩策略类。默认支持的类是'SizeTieredCompactionStrategy'(STCS),'LeveledCompactionStrategy'(LCS)和'TimeWindowCompactionStrategy'(TWCS)('DateTieredCompactionStrategy'也支持,但不推荐使用'TimeWindowCompactionStrategy'。可以通过将完整类名称指定为字符串常量来提供自定义策略。
Compression options
压缩选项定义是否以及如何压缩表的sstables。以下子选项区域可用:
| 选项 | 默认值 | 描述 |
|---|---|---|
class |
LZ4Compressor | 使用的压缩算法。 默认压缩器是:LZ4Compressor,SnappyCompressor和DeflateCompressor。Use'enabled':false禁用压缩。可以通过将完整的类名指定为“字符串常量”来提供自定义压缩器:#constants。 |
enabled |
true | 启用/禁用sstable压缩。 |
chunk_length_in_kb |
64KB | 在磁盘上SSTables被块压缩(允许随机读取)。 这定义了所述块的大小(以KB计)。 较大的值可以提高压缩率,但增加从磁盘读取的数据的最小大小。 |
crc_check_chance |
1.0 | 当启用压缩时,每个压缩块包括该块的校验和,以便检测磁盘bitrot并避免将恶化传播到其他复制品。此选项定义在读取期间检查这些校验和的概率。默认情况下总是选中它。设置为0以禁用校验和检查,0.5设置为每隔一个读取检查它们。 |
Caching options
缓存选项允许为表配置键高速缓存和行高速缓存。以下子选项可用:
| 选项 | 默认值 | 描述 |
|---|---|---|
keys |
ALL | 是否缓存此表的键(“键缓存”)。有效值为:ALL和NONE。 |
rows_per_partition |
NONE | 每个分区缓存的行数(“行缓存”)。 如果指定了整数n,则将高速缓存分区的前n个查询的行。其他可能的选项是,缓存查询分区的所有行,或者禁用行缓存。 |
7.更改表
更改现有表使用ALTER TABLE语句:
alter_table_statement ::= ALTER TABLEtable_namealter_table_instructionalter_table_instruction ::= ALTERcolumn_nameTYPEcql_type| ADDcolumn_namecql_type( ','column_namecql_type)* | DROPcolumn_name(column_name)* | WITHoptions
示例:
ALTER TABLE addamsFamily ALTER lastKnownLocation TYPE uuid; ALTER TABLE addamsFamily ADD gravesite varchar; ALTER TABLE addamsFamily WITH comment = 'A most excellent and useful table' AND read_repair_chance = 0.2;
ALTER TABLE语句可以:
- 更改表中某一列的类型(通过ALTER指令)。 注意,列的类型不能任意改变。 类型的更改应该是先前类型的任何值都应是新类型的有效值。 此外,对于其上定义了二级索引(secondaryindex)的列,新类型必须以与先前类型相同的方式排序值。有关接受哪些类型更改的详细信息,请参阅下面的“类型兼容性”表。
- 向表中添加新列(通过ADD指令)。 请注意,表的主键不能更改,因此新添加扩展的列绝不是主键的一部分。还要注意,紧凑表有关于列添加的限制。添加新列是恒定的(在集群包含的数据量)时间操作。
- 从表中删除列。这会删除列及其所有内容,当列立即不可用时,其内容只会在压缩期间被懒惰删除。请参阅下面的警告。由于延迟删除,更改本身是一个常量(在集群中删除或包含的数据量)时间操作。
- 更改一些表选项(通过WITH指令)。 支持的选项与创建表时(在COMPACT STORAGE和CLUSTERING ORDER之外,在创建后无法更改)相同。设置任何压缩子选项都会删除所有先前的压缩选项,因此如果要保留它们,则需要重新指定所有子选项。
警告:删除列假定用于此列的值的时间戳为“real”时间戳(以微秒为单位)。使用以微秒为单位的“真实”时间戳是默认值,并且强烈推荐,但Cassandra允许客户端在任何表上提供任何时间戳,理论上可以使用另一个规则。如果这样做,删除列将无法正常工作。
警告:删除列后,可以重新添加与删除的列名称相同的列,因为删除列的类型是(非冻结)列。
7-1.CQL兼容类型
CQL数据类型只能按照下表进行转换。
| 现有类型 | 可替换类型 |
|---|---|
| timestamp | bigint |
| ascii, bigint, boolean, date, decimal, double, float,inet, int, smallint, text, time, timestamp, timeuuid,tinyint, uuid, varchar, varint | blob |
| int | date |
| ascii, varchar | text |
| bigint | time |
| bigint | timestamp |
| timeuuid | uuid |
| ascii, text | varchar |
| bigint, int, timestamp | varint |
集群列具有更严格的要求,只允许以下转化:
| 现有类型 | 可替换类型 |
|---|---|
| ascii, text, varchar | blob |
| ascii, varchar | text |
| ascii, text | varchar |
8.删除表
删除表使用DROP TABLE语句:
drop_table_statement ::= DROP TABLE [ IF EXISTS ] table_name
删除表操作会立即执行,不可逆地删除表,包括其包含的所有数据。如果表不存在,则语句将返回错误,除非使用IF EXISTS,在这种情况下,操作是无操作。
9.截断表
可以使用TRUNCATE语句截断表:
truncate_statement ::= TRUNCATE [ TABLE ] table_name
允许TRUNCATE TABLE foo与其他DDL语句的一致性,但是表是当前可以截断的唯一对象,因此可以省略TABLE关键字。
截断表永久删除表中的所有现有数据,但不删除表本身。