Kor*_*nel 6 database cql cassandra nosql cql3
假设一个简单的表有一个插入(或没有这个插入,并不重要).
CREATE TABLE test (
x int,
y int,
z int,
PRIMARY KEY (x, y, z)
);
create index z_index on test (z);
insert into test(x, y, z) values (1,2,3);
Run Code Online (Sandbox Code Playgroud)
我很难理解为什么我不能在索引z上使用in子句进行查询:
cqlsh:test> select*from test其中z in(3);
错误请求:PRIMARY KEY部分z不能被限制(前面部分y不受限制或非EQ关系)
可以使用简单的equals谓词:
cqlsh:test> select * from test where z = 3;
x | y | z
---+---+---
1 | 2 | 3
(0 rows)
Run Code Online (Sandbox Code Playgroud)
我认为在z上有一个索引会保留从z的特定值到行的映射,但这个假设似乎是错误的.
为什么这不符合我的预期?我猜索引的工作方式不同.
编辑:我正在使用[cqlsh 4.1.1 | Cassandra 2.0.6 | CQL规范3.1.1 | 节俭协议19.39.0]
虽然关于DataStax的文档通常非常好,但我找不到任何讨论这背后细节的内容.但是,我确实遇到过这篇名为" 打破CQL WHERE子句 "的文章.第2节的标题是" 分区键中的最后一列支持IN运算符".
换句话说,它基本上是这样说的:
对于单列分区键,允许IN运算符不受限制.对于复合分区键,我必须在分区键的前N-1列上使用=运算符,以便在最后一列上使用IN运算符.
在您的情况下,x是您的分区键,这意味着它x是唯一支持INCQL运算符的列.如果您确实需要能够支持IN列上的查询z,那么您必须对数据进行反规范化,并构建一个旨在支持该查询的(冗余)表.例如:
CREATE TABLE test (
x int,
y int,
z int,
PRIMARY KEY (z)
);
Run Code Online (Sandbox Code Playgroud)
...将支持查询,但值z可能不是唯一的.在这种情况下,您可以定义x和/或y作为a LIST<int>和那样做.
此外,DataStax 确实提供了何时不使用索引的文档,并指出相同的条件适用于IN运算符的使用.
在大多数情况下,不建议在WHERE子句中使用IN.使用IN会降低性能,因为通常必须查询许多节点.例如,在具有30个节点,复制因子为3且一致性级别为LOCAL_QUORUM的单个本地数据中心集群中,单个密钥查询将发送到两个节点,但如果查询使用IN条件,则数量为被查询的节点很可能甚至更高,最多20个节点,具体取决于密钥落在令牌范围内的位置.