Cassandra CQL替代WHERE子句中的OR

时间:2017-06-04 18:43:15

标签: cassandra cql

这是我用来创建表格的代码:

CREATE TABLE test.packages (
     packageuuid timeuuid, 
     ruserid text, 
     suserid text, 
     timestamp int, 
     PRIMARY KEY (ruserid, suserid, packageuuid, timestamp)
);

然后我创建一个物化视图:

CREATE MATERIALIZED VIEW test.packages_by_userid 
    AS SELECT * FROM test.packages 
    WHERE ruserid IS NOT NULL 
       AND suserid IS NOT NULL 
       AND TIMESTAMP IS NOT NULL 
       AND packageuuid IS NOT NULL 
    PRIMARY KEY (ruserid, suserid, timestamp, packageuuid) 
    WITH CLUSTERING ORDER BY (packageuuid DESC);

我希望能够搜索在两个ID之间发送的包

所以我需要这样的东西:

SELECT * FROM test.packages_by_userid WHERE (ruserid = '1' AND suserid = '2' AND suserid = '1' AND ruserid = '2') AND timestamp > 1496601553;

我如何用CQL完成这样的事情?

我搜索了一下,但我无法弄清楚。

我愿意改变桌子的结构,如果它能做到这样的话。

如果在没有物化视图的情况下可行,那也很好。

2 个答案:

答案 0 :(得分:1)

使用条款:

SELECT * FROM test.packages_by_userid WHERE ruserid IN ( '1', '2') AND suserid IN ( '1','2') AND timestamp > 1496601553;

注意:保持in子句的大小更小,分区中的large in子句可能导致GC暂停和堆压力导致整体性能下降

  

实际上,这意味着你正在等待这个单一的协调器节点给你一个响应,它将所有这些查询及其响应保存在堆中,如果其中一个查询失败,或者协调器失败,你有重试整个事情。

如果更大的多分区in子句尝试使用单独的查询,则对于executeAsync的每个分区(ruserid)。

SELECT * FROM test.packages_by_userid WHERE ruserid = '1' AND suserid IN ( '1','2') AND timestamp > 1496601553;
SELECT * FROM test.packages_by_userid WHERE ruserid = '2' AND suserid IN ( '1','2') AND timestamp > 1496601553;

了解详情:https://lostechies.com/ryansvihla/2014/09/22/cassandra-query-patterns-not-using-the-in-query-for-multiple-partitions/

答案 1 :(得分:0)

由于您始终搜索发件人和收件人,我将使用以下表格布局对其进行建模:

CREATE TABLE test.packages (
     ruserid text, 
     suserid text, 
     timestamp int, 
     packageuuid timeuuid, 
     PRIMARY KEY ((ruserid, suserid), timestamp)
);

这样,对于每对发送者/接收者,您需要运行两个查询,每个分区一个:

SELECT * FROM packages WHERE ruserid=1 AND suserid=2 AND timestamp > 1496601553;
SELECT * FROM packages WHERE ruserid=2 AND suserid=1 AND timestamp > 1496601553;

这是恕我直言的最佳解决方案,因为,请记住,在Cassandra中,您从查询开始并在此基础上构建表模型,而不是相反。