【问题标题】:Multi Column equality Restrictions in CassandraCassandra中的多列相等限制
【发布时间】:2016-02-22 01:35:52
【问题描述】:

考虑下表:

CREATE TABLE routes (
start text,
end text,
validFrom timestamp,
validTo timestamp,
PRIMARY KEY (start, end, validFrom, validTo)
);

如何编写一个 cql 查询来查找从 A 点到 B 点并且在日期 x 和日期 y 之间有效的所有路线。本质上相当于下面的 SQL 语句:

SELECT * from routes where start = 'A' and end = 'B' and validFrom <= x and validTo >= y.

我一直在阅读Cassandra Docs,我的印象是,对于给定的表,这样的查询是不可能的。如果是这种情况,那么如何对数据进行建模以启用这样的查询。

【问题讨论】:

    标签: cassandra cql


    【解决方案1】:
    SELECT * from routes where start = 'A' and end = 'B' and validFrom <= x and validTo >= y
    

    由于 Cassandra 将其数据存储在磁盘上的方式,它无法为这样的查询提取连续范围的行。所以你需要做的是稍微调整你的模型。

    CREATE TABLE routes (
      start text,
      end text,
      valid timestamp,
      toFrom text,
      name text,
      PRIMARY KEY (start, end, valid, toFrom)
    );
    

    通过将到/从valid 时间合并到一个列中,您现在可以对其执行范围查询,检查开始和结束。每行需要存储两次。一次是“有效期至”时间,一次是“有效期自”时间。 toFrom 列有助于区分这一点。

    现在我可以运行这个查询了:

    > SELECT * FROM routes 
        WHERE start='A' AND end='B' 
        AND valid>='2016-02-01'AND valid<='2016-02-20';
    
     start | end | valid                    | tofrom | name
    -------+-----+--------------------------+--------+---------
         A |   B | 2016-02-01 06:00:00+0000 |      F | combo 1
         A |   B | 2016-02-14 06:00:00+0000 |      T | combo 1
         A |   B | 2016-02-15 06:00:00+0000 |      F | combo 2
    
    (3 rows)
    

    只是一个想法,但使用复合分区键(如PRIMARY KEY ((start, end), valid, toFrom))来更好地分配数据可能是有意义的。尽管这实际上取决于您的查询模式....因此,如果您需要查询以“A”开头的所有行(例如),这将不起作用。

    编辑 20160221

    我接受了你的回答,但现在我想了更多,我认为这不会奏效。例如。我认为查询: SELECT * FROM routes WHERE start='A' AND end='B' AND valid>='2016-02-01' AND valid

    实际上,确实工作:

    > SELECT * FROM routes 
        WHERE start='A' AND end='B' 
        AND valid>='2016-02-01'AND valid<='2016-02-13';
    
     start | end | valid                    | tofrom | name
    -------+-----+--------------------------+--------+---------
         A |   B | 2016-02-01 06:00:00+0000 |      F | combo 1
    
    (1 rows)
    

    话虽如此,我明白你的意思。如果您应该选择在有效到/从(不包括在内)之间发生的时间段,它将产生零行......像这样:

        > SELECT * FROM routes 
        WHERE start='A' AND end='B' 
        AND valid>='2016-02-02'AND valid<='2016-02-13';
    
     start | end | valid                    | tofrom | name
    -------+-----+--------------------------+--------+---------
    
    (0 rows)
    

    这是一个合理的担忧。关于这一点的两点:

    1. 就您要求“等同于以下 SQL 语句” 的问题而言,您在关系数据库中仍然会遇到同样的问题(在我的 MariaDB 测试实例上尝试过) )。实际上,情况会更糟,因为 valid&gt;='2016-02-01'AND valid&lt;='2016-02-13' 的查询在 Cassandra 中返回一行,但 validFrom&gt;='2016-02-01' AND validTo&lt;='2016-02-13' 在 MariaDB 中没有返回任何内容。

    2. 这确实成为一个业务逻辑问题,与您的数据存储无关。为避免此问题,您应该查看您的业务逻辑/需求,并确定valid 与/从之间的最长时间。然后,您可以调整查询,使其始终超过该时间。示例:如果路由最多只能在两三周内有效,那么一次查询一个月就足够了。

    【讨论】:

    • 啊-我接受了你的回答,但现在我想了更多,我认为这行不通。例如。我认为查询:SELECT * FROM routes WHERE start='A' AND end='B' AND valid&gt;='2016-02-01' AND valid&lt;='2016-02-13'; 不会产生任何结果,即使“组合 1”路由应该是有效的。
    • 道歉 - 我在原始 sql 语句中打错了字。它应该是 validFrom 。我刚刚重新接受了你的回答,因为它当然回答了我原来的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-14
    • 1970-01-01
    • 2014-01-20
    • 1970-01-01
    • 2015-04-18
    • 2015-03-05
    • 2017-03-19
    相关资源
    最近更新 更多