Data Definition
tables, whose schema defines the layout of the data in the table. Tables are located in keyspaces. A keyspace defines options that apply to all the keyspace’s tables. The replication strategy is an important keyspace option, as is the replication factor. A good general rule is one keyspace per application. It is common for a cluster to define only one keyspace for an active application. This section describes the statements used to create, modify, and remove those keyspace and tables.
Common definitions
The names of the keyspaces and tables are defined by the following grammar:
keyspace_name::= nametable_name::= [keyspace_name '.' ] namename::= unquoted_name | quoted_nameunquoted_name::= re('[a-zA-Z_0-9]\{1, 48}')quoted_name::= '"' unquoted_name '"'
myTable is equivalent to mytable) but case sensitivity can be forced by using double-quotes ("myTable" is different from mytable).
current keyspace (see USE statement).
Further, the valid names for columns are defined as:
column_name::= identifier
We also define the notion of statement options for use in the following section:
options::= option ( AND option )*option::= identifier '=' ( identifier | constant | map_literal )
CREATE KEYSPACE
CREATE KEYSPACE statement:
create_keyspace_statement::= CREATE KEYSPACE [ IF NOT EXISTS ] keyspace_name WITH options
For example:
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;
IF NOT EXISTS option is used. If it is used, the statement will be a no-op if the keyspace already exists.
options are:
replication property is mandatory and must contain the 'class' sub-option that defines the desired replication strategy class. The rest of the sub-options depend on which replication strategy is used. By default, Cassandra supports the following 'class' values:
SimpleStrategy
NetworkTopologyStrategy. SimpleStrategy supports a single mandatory argument:
NetworkTopologyStrategy
A production-ready replication strategy that sets the replication factor independently for each data-center. The rest of the sub-options are key-value pairs, with a key set to a data-center name and its value set to the associated replication factor. Options:
replication_factor, auto-expansion will only add new datacenters for safety, it will not alter existing datacenters or remove any, even if they are no longer in the cluster. If you want to remove datacenters while setting the replication_factor, explicitly zero out the datacenter you want to have zero replicas.
DC1 and DC2:
CREATE KEYSPACE excalibur WITH replication = {'class': 'NetworkTopologyStrategy', 'replication_factor' : 3};DESCRIBE KEYSPACE excalibur;
will result in:
CREATE KEYSPACE excalibur WITH replication = {'class': 'NetworkTopologyStrategy', 'DC1': '3', 'DC2': '3'} AND durable_writes = true;
An example of auto-expanding and overriding a datacenter:
CREATE KEYSPACE excalibur WITH replication = {'class': 'NetworkTopologyStrategy', 'replication_factor' : 3, 'DC2': 2};DESCRIBE KEYSPACE excalibur;
will result in:
CREATE KEYSPACE excalibur WITH replication = {'class': 'NetworkTopologyStrategy', 'DC1': '3', 'DC2': '2'} AND durable_writes = true;
replication_factor:
CREATE KEYSPACE excalibur WITH replication = {'class': 'NetworkTopologyStrategy', 'replication_factor' : 3, 'DC2': 0};DESCRIBE KEYSPACE excalibur;
will result in:
CREATE KEYSPACE excalibur WITH replication = {'class': 'NetworkTopologyStrategy', 'DC1': '3'} AND durable_writes = true;
transient replication has been enabled, transient replicas can be configured for both SimpleStrategy and NetworkTopologyStrategy by defining replication factors in the format '<total_replicas>/<transient_replicas>'
For instance, this keyspace will have 3 replicas in DC1, 1 of which is transient, and 5 replicas in DC2, 2 of which are transient:
CREATE KEYSPACE some_keyspace WITH replication = {'class': 'NetworkTopologyStrategy', 'DC1' : '3/1'', 'DC2' : '5/2'};
USE
USE statement changes the current keyspace to the specified keyspace. A number of objects in CQL are bound to a keyspace (tables, user-defined types, functions, etc.) and the current keyspace is the default keyspace used when those objects are referred to in a query without a fully-qualified name (without a prefixed keyspace name). A USE statement specifies the keyspace to use as an argument:
use_statement::= USE keyspace_name
Using CQL:
USE excelsior;
ALTER KEYSPACE
ALTER KEYSPACE statement modifies the options of a keyspace:
alter_keyspace_statement::= ALTER KEYSPACE [ IF EXISTS ] keyspace_name WITH options
For example:
ALTER KEYSPACE excelsior WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 4};
IF EXISTS is used in which case the operation is a no-op. The supported options are the same as for creating a keyspace.
DROP KEYSPACE
DROP KEYSPACE statement:
drop_keyspace_statement::= DROP KEYSPACE [ IF EXISTS ] keyspace_name
For example:
DROP KEYSPACE excelsior;
Dropping a keyspace results in the immediate, irreversible removal of that keyspace, including all the tables, user-defined types, user-defined functions, and all the data contained in those tables.
IF EXISTS is used in which case the operation is a no-op.
CREATE TABLE
CREATE TABLE statement:
create_table_statement::= CREATE TABLE [ IF NOT EXISTS ] table_name '(' column_definition ( ',' column_definition )* [ ',' PRIMARY KEY '(' primary_key ')' ] ')' [ WITH table_options ]column_definition::= column_name cql_type [ STATIC ] [ column_mask ] [ PRIMARY KEY]column_mask::= MASKED WITH ( DEFAULT | function_name '(' term ( ',' term )* ')' )primary_key::= partition_key [ ',' clustering_columns ]partition_key::= column_name | '(' column_name ( ',' column_name )* ')'clustering_columns::= column_name ( ',' column_name )*table_options::= COMPACT STORAGE [ AND table_options ] | CLUSTERING ORDER BY '(' clustering_order ')' [ AND table_options ] | optionsclustering_order::= column_name (ASC | DESC) ( ',' column_name (ASC | DESC) )*
For example, here are some CQL statements to create tables:
CREATE TABLE monkey_species ( species text PRIMARY KEY, common_name text, population varint, average_size int) WITH comment='Important biological records';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);
rows. Creating a table amounts to defining which columns each rows will have, which of those columns comprise the primary key, as well as defined options for the table.
IF NOT EXISTS directive is used. If it is used, the statement will be a no-op if the table already exists.
Column definitions
alter statement.
column_definition is comprised of the name of the column and its type, restricting the values that are accepted for that column. Additionally, a column definition can have the following modifiers:
STATIC: declares the column as a static columnPRIMARY KEY: declares the column as the sole component of the primary key of the tableStatic columns
STATICin a table definition. A column that is static will be “shared” by all the rows belonging to the same partition (having the same partition key. For example:- Code
- Results
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'
svalue is the same (static1) for both of the rows in the partition (the partition key beingpk, and both rows are in the same partition): the second insertion overrides the value fors. The use of static columns has the following restrictions: - A table without clustering columns cannot have static columns. In a table without clustering columns, every partition has only one row, and so every column is inherently static)
- Only non-primary key columns can be static.
The Primary key
PRIMARY KEY, and hence all tables must define a single PRIMARY KEY. APRIMARY KEYis composed of one or more of the defined columns in the table. Syntactically, the primary key is defined with the phrasePRIMARY KEYfollowed by a comma-separated list of the column names within parenthesis. If the primary key has only one column, you can alternatively add thePRIMARY KEYphrase to that column in the table definition. The order of the columns in the primary key definition defines the partition key and clustering columns. A CQL primary key is composed of two parts: partition key - It is the first component of the primary key definition. It can be a single column or, using an additional set of parenthesis, can be multiple columns. A table must have at least one partition key, the smallest possible table definition is:
CREATE TABLE t (k text PRIMARY KEY);
clustering columns
- clustering order. Some examples of primary key definition are:
PRIMARY KEY (a):ais the single partition key and there are no clustering columnsPRIMARY KEY (a, b, c):ais the single partition key andbandcare the clustering columnsPRIMARY KEY ((a, b), c):aandbcompose the composite partition key andcis the clustering columnPartition key
partition that defines the location of data within a Cassandra cluster. A partition is the set of rows that share the same value for their partition key. Note that if the partition key is composed of multiple columns, then rows belong to the same partition when they have the same values for all those partition key columns. A hash is computed from the partition key columns and that hash value defines the partition location. So, for instance, given the following table definition and content:
will result inCREATE TABLE t ( a int, b int, c int, d int, PRIMARY KEY ((a, b), c, d));INSERT INTO t (a, b, c, d) VALUES (0,0,0,0);INSERT INTO t (a, b, c, d) VALUES (0,0,1,1);INSERT INTO t (a, b, c, d) VALUES (0,1,2,2);INSERT INTO t (a, b, c, d) VALUES (0,1,3,3);INSERT INTO t (a, b, c, d) VALUES (1,1,4,4);SELECT * FROM t;
a | b | c | d---+---+---+--- 0 | 0 | 0 | 0 (1) 0 | 0 | 1 | 1 0 | 1 | 2 | 2 (2) 0 | 1 | 3 | 3 1 | 1 | 4 | 4 (3)(5 rows)
clustering columns, then every partition of that table has a single row. because the partition key, compound or otherwise, identifies a single location. atomic and done in isolation, the partitions must be sized “just right, not too big nor too small”. Data modeling that considers the querying patterns and assigns primary keys based on the queries will have the lowest latency in fetching data.Clustering columns
partition, all rows are ordered by that clustering order. Clustering columns also add uniqueness to a row in a table. For instance, given:
will result inCREATE TABLE t2 ( a int, b int, c int, d int, PRIMARY KEY (a, b, c));INSERT INTO t2 (a, b, c, d) VALUES (0,0,0,0);INSERT INTO t2 (a, b, c, d) VALUES (0,0,1,1);INSERT INTO t2 (a, b, c, d) VALUES (0,1,2,2);INSERT INTO t2 (a, b, c, d) VALUES (0,1,3,3);INSERT INTO t2 (a, b, c, d) VALUES (1,1,4,4);SELECT * FROM t2;
a | b | c | d---+---+---+--- 1 | 1 | 4 | 4 (1) 0 | 0 | 0 | 0 0 | 0 | 1 | 1 0 | 1 | 2 | 2 0 | 1 | 3 | 3(5 rows)
bclustering column defines the order in which those rows are displayed. Whereas the partition key of the table groups rows on the same node, the clustering columns control how those rows are stored on the node. That sorting allows the very efficient retrieval of a range of rows within a partition:
will result inSELECT * FROM t2 WHERE a = 0 AND b > 0 and b <= 3;
a | b | c | d---+---+---+--- 0 | 1 | 2 | 2 0 | 1 | 3 | 3(2 rows)
Table options
WITHkeyword.CLUSTERING ORDER BY, influences how queries can be done against the table. It is worth discussing in more detail here.Clustering order
The clustering order of a table is defined by the clustering columns. By default, the clustering order is ascending for the clustering column’s data types. For example, integers order from 1, 2, … n, while text orders from A to Z.CLUSTERING ORDER BYtable option uses a comma-separated list of the clustering columns, each set for eitherASC(for ascending order) orDESC(for _descending order). The default is ascending for all clustering columns if theCLUSTERING ORDER BYoption is not set. This option is basically a hint for the storage engine that changes the order in which it stores the row. Beware of the consequences of setting this option:SELECTstatement with noORDER BYclause.ORDER BYclause is used inSELECTstatements on that table. Results can only be ordered with either the original clustering order or the reverse clustering order. Suppose you create a table with two clustering columnsaandb, definedWITH CLUSTERING ORDER BY (a DESC, b ASC). Queries on the table can useORDER BY (a DESC, b ASC)orORDER BY (a ASC, b DESC). Mixed order, such asORDER BY (a ASC, b ASC)orORDER BY (a DESC, b DESC)will not return expected order.WITH CLUSTERING ORDER BY (). This optimization is common for time series, to retrieve the data from newest to oldest.Other table options
A table supports the following options:Speculative retry options
ONE, a quorum forQUORUM, and so on.speculative_retrydetermines when coordinators may query additional replicas, a useful action when replicas are slow or unresponsive. Speculative retries reduce the latency. The speculative_retry option configures rapid read protection, where a coordinator sends more requests than needed to satisfy the consistency level. Pre-Cassandra 4.0 speculative retry policy takes a single string as a parameter:NONEALWAYS99PERCENTILE(PERCENTILE)50MS(CUSTOM) An example of setting speculative retry sets a custom value:
This example uses a percentile for the setting:ALTER TABLE users WITH speculative_retry = '10ms';
ALTER TABLE users WITH speculative_retry = '99PERCENTILE';
p99will not speculate as intended because the value at the specified percentile has increased too much. If the consistency level is set toALL, all replicas are queried regardless of the speculative retry setting. CASSANDRA-14293). For example, assigning the value asnone,None, orNONEhas the same effect. Additionally, the following values are added:MIN()andMAX()speculative retry policies, with a mix and match of eitherMIN(), MAX(),MIN(), MIN(), orMAX(), MAX()(CASSANDRA-14293). The hybrid mode will still speculate if the normalp99for the table is < 50ms, the minimum value. But if thep99level goes higher than the maximum value, then that value can be used. In a hybrid value, one value must be a fixed time (ms) value and the other a percentile value. To illustrate variations, the following examples are all valid:min(99percentile,50ms)max(99p,50MS)MAX(99P,50ms)MIN(99.9PERCENTILE,50ms)max(90percentile,100MS)MAX(100.0PERCENTILE,60ms)
additional_write_policysetting specifies the threshold at which a cheap quorum write will be upgraded to include transient replicas.Compaction options
compactionoptions must minimally define the'class'sub-option, to specify the compaction strategy class to use. The supported classes are:'SizeTieredCompactionStrategy', STCS (Default)'LeveledCompactionStrategy', LCS'TimeWindowCompactionStrategy', TWCS string constant. common options, as well as options specific to the strategy chosen. See the section corresponding to your strategy for details: STCS, LCS, TWCS.Compression options
compressionoptions define if and how the SSTables of the table are compressed. Compression is configured on a per-table basis as an optional argument toCREATE TABLEorALTER TABLE. The following sub-options are available:chunk_length_in_kbof 4 KB:CREATE TABLE simple ( id int, key text, value text, PRIMARY KEY (key, value)) WITH compression = {'class': 'LZ4Compressor', 'chunk_length_in_kb': 4};
Caching options
cachingoptions can configure both thekey cacheand therow cachefor the table. The following sub-options are available: For instance, to create a table with both a key cache and 10 rows cached per partition:CREATE TABLE simple (id int,key text,value text,PRIMARY KEY (key, value)) WITH caching = {'keys': 'ALL', 'rows_per_partition': 10};
Read Repair options
read_repairoptions configure the read repair behavior, tuning for various performance and consistency behaviors. The values are: Two consistency properties are affected by read repair behavior.BLOCKINGprovides this behavior.NONEprovides this behavior.Other considerations:
ALTER TABLEbelow) is a constant time operation. Thus, there is no need to anticipate future usage while initially creating a table.ALTER TABLE
ALTER TABLEstatement:alter_table_statement::= ALTER TABLE [ IF EXISTS ] table_name alter_table_instructionalter_table_instruction::= ADD [ IF NOT EXISTS ] column_definition ( ',' column_definition)* | DROP [ IF EXISTS ] column_name ( ',' column_name )* | RENAME [ IF EXISTS ] column_name to column_name (AND column_name to column_name)* | ALTER [ IF EXISTS ] column_name ( column_mask | DROP MASKED ) | WITH optionscolumn_definition::= column_name cql_type [ column_mask]column_mask::= MASKED WITH ( DEFAULT | function_name '(' term ( ',' term )* ')' )
IF EXISTSis used in which case the operation is a no-op. For example:ALTER TABLE addamsFamily ADD gravesite varchar;ALTER TABLE addamsFamily WITH comment = 'A most excellent and useful table';
ALTER TABLEstatement can:ADDa new column to a table. The primary key of a table cannot ever be altered. A new column, thus, cannot be part of the primary key. Adding a column is a constant-time operation based on the amount of data in the table. If the new column already exists, the statement will return an error, unlessIF NOT EXISTSis used in which case the operation is a no-op.DROPa column from a table. This command drops both the column and all its content. Be aware that, while the column becomes immediately unavailable, its content are removed lazily during compaction. Because of this lazy removal, the command is a constant-time operation based on the amount of data in the table. Also, it is important to know that once a column is dropped, a column with the same name can be re-added, unless the dropped column was a non-frozen column like a collection. If the dropped column does not already exist, the statement will return an error, unlessIF EXISTSis used in which case the operation is a no-op.RENAMEa primary key column of a table. Non primary key columns cannot be renamed. Furthermore, renaming a column to another name which already exists isn’t allowed. It’s important to keep in mind that renamed columns shouldn’t have dependent seconday indexes. If the renamed column does not already exist, the statement will return an error, unlessIF EXISTSis used in which case the operation is a no-op.WITHto change a table option. The supported options are the same as those used when creating a table, with the exception ofCLUSTERING ORDER. However, setting anycompactionsub-options will erase ALL previouscompactionoptions, so you need to re-specify all the sub-options you wish to keep. The same is true forcompressionsub-options.DROP TABLE
DROP TABLEstatement:
Dropping a table results in the immediate, irreversible removal of the table, including all data it contains.drop_table_statement::= DROP TABLE [ IF EXISTS ] table_name
IF EXISTSis used, when the operation is a no-op.TRUNCATE TABLE
TRUNCATEstatement:truncate_statement::= TRUNCATE [ TABLE ] table_name
TRUNCATE TABLE foois the preferred syntax for consistency with other DDL statements. However, tables are the only object that can be truncated currently, and theTABLEkeyword can be omitted. Truncating a table permanently removes all existing data from the table, but without removing the table itself.
