如果表具有SET类型列,则Cassandra IN查询无效

时间:2015-02-02 12:53:02

标签: cassandra cql

我是Cassandra的新手。我在CQL IN query中遇到了一个问题,如果表格有SET类型列,那么它就可以了。

CREATE TABLE test (
    test_date bigint, 
    test_id bigint, 
    caption text,
    PRIMARY KEY(test_date,test_id)
);

select * from test where test_date = 2022015 and test_id IN (1,2);

但如果我在上面添加标签设置,则会出错

CREATE TABLE test1 (
    test_date bigint, 
    test_id bigint, 
    tags set<text>,
    caption text,
    PRIMARY KEY(test_date,test_id)
);

select * from test1 where test_date = 2022015 and test_id IN (1,2);
  

code = 2200 [无效查询] message =“无法限制列”test_id“   作为集合的IN关系由查询“

选择

3 个答案:

答案 0 :(得分:3)

我不确定为什么这种限制特别适用于收藏品。但在您的情况下,您可以通过将test_id作为分区键的一部分来解决此问题:

PRIMARY KEY((test_date,test_id))

只要您指定复合键的第一部分(test_date),这将允许您执行IN查询。

答案 1 :(得分:3)

我认为你看到这个错误是由于Cassandra的底层存储模型。当我在CQLSH中查询你的test1表(使用我自己的测试数据)时,这就是我所看到的:

aploetz@cqlsh:stackoverflow> SELECT * FROM test1;

 test_date | test_id | caption   | tags
-----------+---------+-----------+-------------------------
   2022015 |       1 | blah blah | {'one', 'three', 'two'}
   2022015 |       2 | blah blah | {'one', 'three', 'two'}

(2 rows)

此视图对数据的实际存储方式提供了误导性解释。当我从cassandra-cli中查询同一个表时,这就是它的样子:

[default@stackoverflow] list test1;
Using default limit of 100
Using default cell limit of 100
-------------------
RowKey: 2022015
=> (name=1:, value=, timestamp=1422895168730184)
=> (name=1:caption, value=626c616820626c6168, timestamp=1422895168730184)
=> (name=1:tags:6f6e65, value=, timestamp=1422895168730184)
=> (name=1:tags:7468726565, value=, timestamp=1422895168730184)
=> (name=1:tags:74776f, value=, timestamp=1422895168730184)
=> (name=2:, value=, timestamp=1422895161891116)
=> (name=2:caption, value=626c616820626c6168, timestamp=1422895161891116)
=> (name=2:tags:6f6e65, value=, timestamp=1422895161891116)
=> (name=2:tags:7468726565, value=, timestamp=1422895161891116)
=> (name=2:tags:74776f, value=, timestamp=1422895161891116)

1 Row Returned.

这表明集合(集)值存储为附加列键。使用IN关系的限制是它必须在主键的最后一个键(分区或聚类)上运行。所以我猜这是一个基于Cassandra如何“隐藏”收集数据的限制。

只是一个警告,但不建议使用IN进行生产级查询。有些人甚至将其列入Cassandra反模式列表。我对此问题的回答(Is the IN relation in Cassandra bad for queries?)解释了为什么IN查询不是最优的。

修改

只是为了看,我尝试使用列表而不是集合来构建模式,看看是否有任何区别。它仍然不起作用,但是从cassandra-cli中它似乎向键添加了一个额外的UUID标识符,并将实际值存储为列值。这与集合的处理方式不同......这必须是集合如何限制为唯一值。

答案 2 :(得分:0)

如果更改基表上的PK不是一个选项,您可以使用带有test_id的物化视图作为分区表达式的一部分来满足您的要求:

CREATE MATERIALIZED VIEW test1_mv AS
SELECT * FROM test1
WHERE test_date IS NOT NULL AND test_id IS NOT NULL
PRIMARY KEY((test_date,test_id));

然后在查询中使用物化视图而不是基表:

select * from test1_mv where test_date = 2022015 and test_id IN (1,2);