如果表具有SET类型列,则Cassandra IN查询不起作用

mbjcgjjk  于 2023-02-08  发布在  Cassandra
关注(0)|答案(3)|浏览(151)

我是新来的Cassandra。我有一个问题时,使用在Cassandra查询。
如果表中没有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);

但是,如果我在上表中添加SET类型的列(例如,标记set)并重新运行选择查询,则会出现错误。

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=“无法通过IN关系限制列“test_id”,因为查询选择了一个集合”

ui7jx7zq

ui7jx7zq1#

我不知道为什么这个限制应该特别适用于集合,但是在您的情况下,您可以通过将test_id作为分区键的一部分来解决这个问题:
PRIMARY KEY((test_date,test_id))
这将允许您执行IN查询,只要您指定了组合键的第一部分(test_date)。

dgtucam1

dgtucam12#

我认为您看到的这个错误是由于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反模式列表中。我对这个问题的回答(Cassandra中的IN关系对查询不好吗?)解释了为什么IN查询不是最优的。

    • 编辑**

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

hfyxw5xn

hfyxw5xn3#

如果无法更改基表上的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);

相关问题