我以前说过,现在我再说一遍:
二级索引也是如此。
任何时候,如果您不筛选
WHERE
子句,则运行所谓的“多键查询”这是一种已知的反模式,因为它不能将自身限制为一个分区,因此查询需要引用多个节点才能完成。这是一种
不会缩放
,因此使用
分布式
数据库
在Cassandra中,您需要采用基于查询的建模方法。据我所知,你
id
定义为单独的主键,但不是通过它进行查询。主键定义应该真正反映希望表提供服务的查询类型。
如果这是您要运行的查询,那么您的表定义将需要反映:
CREATE TABLE test_by_a_and_c (
id uuid,
a int,
b int,
c varchar,
d varchar,
timestamp bigint,
PRIMARY KEY (a,c,timestamp,id));
这将按以下方式对数据进行分区
a
,并按
c
,
timestamp
和
身份证件
. 使用
c
因为您的第一个集群键将允许您的查询工作。使用
时间戳
因为第二个聚类键将允许您的结果按时间戳排序。
身份证件
在末端添加,以确保唯一性,这可能是必要的,也可能不是必要的。此定义将允许此查询工作:
SELECT * FROM test_by_a_and_c WHERE a = 1 AND c < '2';
对于第二个查询,您需要创建
新
包含相同数据的表,并相应调整主键定义:
CREATE TABLE test_by_c_and_a (
id uuid,
a int,
b int,
c varchar,
d varchar,
timestamp bigint,
PRIMARY KEY (c,a,timestamp,id));
此定义将按以下方式对数据进行分区
c
,然后使用
一
作为满足所需查询的第一个群集键:
SELECT * FROM test_by_c_and_a WHERE c = '2' AND a > 1;
Cassandra保证分区存储在单个节点上。因此,通过使用一个好的分区键来限制您的模型,您基本上可以确保您的查询只需转到一个要解决的节点,从而大大减少了所需的网络时间。
另外,我想按时间戳订购。有人能解释为什么卡桑德拉
这样的行为?
Cassandra只能在分区键内强制执行排序顺序。群集顺序本质上是数据写入磁盘的方式。如果未在中指定分区键
哪里
子句,或者当查询可能包含多个键时,数据在读取时返回。首先,它将按照分区键的哈希标记值进行排序。然后,它将通过集群键,相对于当前分区键。
例如,让我以您的第一个查询表为例
INSERT
一些随机数据。如果我在没有
哪里
子句中,您可以看到分区键的哈希标记值是如何发挥作用的:
cassdba@cqlsh:stackoverflow>通过\u a\u和\u c从test\u中选择令牌(a)、a、b、c、d、timestamp;
system.token(a) | a | b | c | d | timestamp
----------------------+---+---+---+---+---------------------
-4069959284402364209 | 1 | 2 | 7 | 2 | 2017-12-14 16:33:55
-4069959284402364209 | 1 | 1 | 8 | 1 | 2017-12-14 16:33:55
-3248873570005575792 | 2 | 2 | 3 | 2 | 2017-12-14 16:33:55
-3248873570005575792 | 2 | 1 | 9 | 1 | 2017-12-14 16:33:55
-2729420104000364805 | 4 | 1 | 6 | 1 | 2017-12-14 16:33:56
-2729420104000364805 | 4 | 2 | 7 | 2 | 2017-12-14 16:33:57
9010454139840013625 | 3 | 2 | 4 | 2 | 2017-12-14 16:33:56
9010454139840013625 | 3 | 1 | 5 | 1 | 2017-12-14 16:33:56
(8 rows)
请注意,分区键的值
一
因其标记,按1、2、4、3顺序返回。此外
时间戳
仅与每个
一
.
如何设计数据库以支持任何组合?
你不能。对于Cassandra,您的查询
必须
提前知道。
那么您的表必须设计为服务于这些查询。如果需要更动态的查询模型,则需要使用更适合该模型的数据存储。