Cassandra 的数据结构
Cassandra的数据结构
Cassandra的Column Family具有类似于以下二维映射的结构。
Map<RowKey, SortedMap<ColumnKey, ColumnValue>>
上述的 RowKey 在 CQL 中被称为分区键(Partition Key),根据这个分区键将数据分配到节点上。
此外,在 CQL 中,主键且不是分区键的 ColumnKey 被称为聚簇列(Clustering Column)(顾名思义,它用于在某个分区中创建键值块)。
当在单个分区上发生大量的读写操作时,会导致特定节点的负载增加。为了考虑负载均衡,需要确定分区键。
通过CQL创建的数据的物理结构
创建以下类型的表,并插入数据。
CREATE KEYSPACE key_space_test WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 };
use key_space_test;
CREATE TABLE testtable (
pkey1 text,
pkey2 text,
skey int,
value text,
cvalue map<text,text>,
PRIMARY KEY ((pkey1, pkey2), skey)
) WITH CLUSTERING ORDER BY (skey DESC);
INSERT INTO testtable (pkey1, pkey2, skey, cvalue, value)
VALUES('pkey1_1', 'pkey2_1', 100, {'hoge': 'fuga'}, 'value11_100');
INSERT INTO testtable (pkey1, pkey2, skey, cvalue, value)
VALUES('pkey1_2', 'pkey2_1', 200, {'hoge': 'fuga'}, 'value21_200');
INSERT INTO testtable (pkey1, pkey2, skey, cvalue, value)
VALUES('pkey1_1', 'pkey2_2', 101, {'hoge1': 'fuga1'}, 'value12_101');
INSERT INTO testtable (pkey1, pkey2, skey, cvalue, value)
VALUES('pkey1_1', 'pkey2_3', 102, {'hoge1': 'fuga1'}), 'value13_102';
INSERT INTO testtable (pkey1, pkey2, skey, cvalue, value)
VALUES('pkey1_1', 'pkey2_1', 101, {'hoge1': 'fuga1'}, 'value11_101');
INSERT INTO testtable (pkey1, pkey2, skey, cvalue, value)
VALUES('pkey1_1', 'pkey2_1', 103, {'hoge1': 'fuga1'}, 'value11_103');
INSERT INTO testtable (pkey1, pkey2, skey, cvalue, value)
VALUES('pkey1_1', 'pkey2_1', 102, {'hoge1': 'fuga1'}, 'value11_102');
NSERT INTO testtable (pkey1, pkey2, skey, cvalue, value)
VALUES('pkey1_1', 'pkey2_1', 12, {'hoge': 'fuga'}, 'value11_12')
cqlsh> use key_space_test ;
cqlsh:key_space_test> select * from testtable;
pkey1 | pkey2 | skey | cvalue | value
---------+---------+------+--------------------+-------------
pkey1_1 | pkey2_1 | 103 | {'hoge1': 'fuga1'} | value11_103
pkey1_1 | pkey2_1 | 102 | {'hoge1': 'fuga1'} | value11_102
pkey1_1 | pkey2_1 | 101 | {'hoge1': 'fuga1'} | value11_101
pkey1_1 | pkey2_1 | 100 | {'hoge': 'fuga'} | value11_100
pkey1_1 | pkey2_1 | 12 | {'hoge': 'fuga'} | value11_12
pkey1_2 | pkey2_1 | 200 | {'hoge': 'fuga'} | value21_200
pkey1_1 | pkey2_3 | 102 | {'hoge1': 'fuga1'} | value13_102
pkey1_1 | pkey2_2 | 101 | {'hoge1': 'fuga1'} | value12_101
(7 rows)
如果使用cassandra-cli查看上述状态,会显示如下信息。
[default@unknown] use key_space_test;
Authenticated to keyspace: key_space_test
[default@key_space_test] list testtable;
Using default limit of 100
Using default cell limit of 100
-------------------
RowKey: pkey2_1:pkey2_1
-------------------
RowKey: pkey1_1:pkey2_1
=> (name=103:, value=, timestamp=1409032006570000)
=> (name=103:cvalue:686f676531, value=6675676131, timestamp=1409032006570000)
=> (name=103:value, value=76616c756531315f313033, timestamp=1409049933189000)
=> (name=102:, value=, timestamp=1409032011667000)
=> (name=102:cvalue:686f676531, value=6675676131, timestamp=1409032011667000)
=> (name=102:value, value=76616c756531315f313032, timestamp=1409049943179000)
=> (name=101:, value=, timestamp=1409031979603000)
=> (name=101:cvalue:686f676531, value=6675676131, timestamp=1409031979603000)
=> (name=101:value, value=76616c756531315f313031, timestamp=1409049954219000)
=> (name=100:, value=, timestamp=1409029158989000)
=> (name=100:cvalue:686f6765, value=66756761, timestamp=1409029158989000)
=> (name=100:value, value=76616c756531315f313030, timestamp=1409049974715000)
=> (name=12:, value=, timestamp=1409051010713000)
=> (name=12:cvalue:686f6765, value=66756761, timestamp=1409051010713000)
=> (name=12:value, value=76616c756531315f3132, timestamp=1409051010713000)
-------------------
RowKey: pkey1_2:pkey2_1
=> (name=200:, value=, timestamp=1409029194029000)
=> (name=200:cvalue:686f6765, value=66756761, timestamp=1409029194029000)
=> (name=200:value, value=76616c756532315f323030, timestamp=1409050124020000)
-------------------
RowKey: pkey1_1:pkey2_3
=> (name=102:, value=, timestamp=1409029279630000)
=> (name=102:cvalue:686f676531, value=6675676131, timestamp=1409029279630000)
=> (name=102:value, value=76616c756531335f313032, timestamp=1409050027490000)
-------------------
RowKey: pkey1_1:pkey2_2
=> (name=101:, value=, timestamp=1409029232070000)
=> (name=101:cvalue:686f676531, value=6675676131, timestamp=1409029232070000)
=> (name=101:value, value=76616c756531325f313031, timestamp=1409050045987000)
5 Rows Returned.
Elapsed time: 154 msec(s).
总之(),
-
- CQL で複数の Partition Key (上記の例では pkey1, pkey2) を指定すると、PKに指定した 値 が ‘:’ で繋がれて一つの RowKey になる。
-
- ColumnKey は Partition Key でないカラムキー名を ‘:’ で繋いだものになる (例外として 主キーとして指定されたキーは、値が使用される)
この理由により、CLUSTERING ORDER に指定できるキーが主キーに制限されている
Map のキーは :<キー名> のフォーマットで ColumnKey の一部になる
CQL の CLUSTERING ORDER に指定したキーは、ColumnKey に 値 が入りソートされる (valueに入れてもソートできないため)
値の型がinteger だと、ちゃんと数値の大小でソートされる (キーに入ってるのにどうやって型を識別してるのか不明。素晴らしい)
当在CQL中指定非RowKey的主键(聚簇列:如上例中的skey),则非RowKey的主键的值将被设置为ColumnKey,并与其他键分离。这样,它具有主键的行为。
与 DynamoDB 相比较
DynamoDB的数据结构
如上所述,DynamoDB的Hash Key就相当于Cassandra的RowKey。这一点完全吻合。
而Range Key则是Cassandra中连接了非RowKey的主键的组合成的。
索引
在Cassandra中,可以创建类似于DynamoDB的“本地辅助索引”(可能)的索引。
什么时候不应该使用索引?
-
- カーディナリティが高い (値の種類が多い)データ
-
- 頻繁に更新されるカラム
- 大量のカラムがあるpartition中でindexでナロイングする場合
相反地,使用的时机我不太明白。
在Cassandra上的搜索
(Cassandra is a popular open-source distributed database management system.)
可以在SELECT语句的WHERE子句中指定的键
-
- Partition Key: 指定する場合、全てのPartition Keyの指定が必須
-
- Partition Key以外の主キー。数値/日時の比較には大小関係の比較が可能。
- Indexを付けたキー (not 主キー)
如果在查询时不指定分区键,查询将跨越多个分区,因此需要添加ALLOW FILTERING选项。
如果添加了此选项,在数据量很大时,查询时间将不确定,因此应尽量避免使用,应该设计能够执行查询而不添加此选项的表结构。