【问题标题】:Cassandra CQL alternative to OR in WHERE clauseCassandra CQL 在 WHERE 子句中替代 OR
【发布时间】:2017-06-05 16:32:20
【问题描述】:

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

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 完成这样的事情?

我已经搜索了一些,但我无法弄清楚。

我愿意改变表格的结构,如果它能让这样的事情成为可能。

如果没有物化视图也是可行的,那也很好。

【问题讨论】:

    标签: cassandra cql


    【解决方案1】:

    在子句中使用:

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

    注意:保持 in 子句的大小更小,分区中的大 in 子句会导致 GC 暂停和堆压力,从而导致整体性能变慢

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

    如果子句中的多个分区较大,请尝试使用单独的查询,对于每个分区(ruserid)使用executeAsync

    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/

    【讨论】:

    • 再次感谢! in 子句将始终涉及两个用户 ID,所以希望我不会遇到减速问题。
    • 那太好了,那么您可以毫无疑问地使用 in 子句解决方案。
    • 我从未见过带有双 IN 子句。此语法在哪个 Cassandra 版本中有效?你是说(ruserid, suserid) IN (('1', '2'), ('1','2'))
    • @xmas79 这在 Cassandra 3.0 及更高版本中有效
    【解决方案2】:

    由于您总是同时搜索发送者和接收者,我将使用以下表格布局对其进行建模:

    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 中,您从查询开始并在此基础上构建表模型,而不是相反。

    【讨论】:

      猜你喜欢
      • 2018-09-19
      • 2017-01-01
      • 1970-01-01
      • 2016-06-12
      • 2013-04-23
      • 2016-12-14
      • 2020-02-08
      • 2015-09-13
      • 1970-01-01
      相关资源
      最近更新 更多