【问题标题】:Cassandra IN clause on index索引上的 Cassandra IN 子句
【发布时间】:2014-07-15 11:08:27
【问题描述】:

假设一个简单的表有一个插入(或者没有这个插入,并不重要)。

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);

我很难理解为什么我不能在索引 z 上使用 in 子句进行查询:

cqlsh:test> select * from test where z in (3);
错误请求:PRIMARY KEY 部分 z 不能被限制(前面的部分 y 要么不受限制,要么受非 EQ 关系限制)

可以用一个简单的等于谓词:

cqlsh:test> select * from test where z = 3;

 x | y | z
---+---+---
 1 | 2 | 3

(0 rows)

我认为在 z 上有一个索引可以保持从 z 的特定值到行的映射,但这个假设似乎是错误的。

为什么这不符合我的预期?我猜索引的工作方式不同。

编辑:我正在使用 [cqlsh 4.1.1 |卡桑德拉 2.0.6 | CQL 规范 3.1.1 | Thrift 协议 19.39.0]

【问题讨论】:

    标签: cassandra cql cql3 database nosql


    【解决方案1】:

    虽然 DataStax 上的文档通常非常好,但我找不到任何讨论这背后的细节的东西。然而,我确实看到了这篇名为A deep look at the CQL WHERE clause 的文章。标题为“SELECT 语句的 WHERE 子句限制”的第二部分有几个段落讨论了 IN 限制。

    换个说法,它基本上是这样说的:

    对于单列键,IN 运算符不受限制。对于复合主键,我必须在分区键的前 N-1 列上使用 = 运算符,以便在最后一列上使用 IN 运算符。

    在您的情况下,x 是您的分区键,这意味着 x 是唯一支持 CQL 的 IN 运算符的列。如果您确实需要能够支持对列zIN 查询,那么您将不得不对数据进行反规范化,并构建一个旨在支持该查询的(冗余)表。例如:

    CREATE TABLE test (
     x int,
     y int,
     z int,
     PRIMARY KEY (z)
    );
    

    ...会支持查询,但z 的值可能不是唯一的。在这种情况下,您可以将x 和/或y 定义为LIST<int>,这样就可以了。

    此外,DataStax 确实when not to use an index 上提供了文档,并且他们声明同样的条件适用于IN 运算符的使用。

    在大多数情况下,在 WHERE 子句中使用 IN 不是 推荐的。使用 IN 会降低性能,因为通常很多 必须查询节点。例如,在单个本地数据中心 具有 30 个节点、复制因子为 3 和一致性的集群 LOCAL_QUORUM 级别,单键查询到两个节点,但是 如果查询使用 IN 条件,则查询的节点数 很可能甚至更高,最多 20 个节点,具体取决于 键在令牌范围内。

    【讨论】:

    • 我会调整为“PRIMARY 键中的最后一列支持 IN 运算符。” - 刚刚使用 IN 作为最后一个集群键对其进行了测试。
    • @Scaramouche 更新了包含相同信息的新帖子的链接。
    猜你喜欢
    • 1970-01-01
    • 2011-06-13
    • 2013-02-03
    • 2016-11-01
    • 2020-08-18
    • 2020-10-19
    • 2019-11-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多