【问题标题】:How to perform query with cassandra's timestamp column as WHERE condition如何使用 cassandra 的时间戳列作为 WHERE 条件执行查询
【发布时间】:2016-06-13 15:09:08
【问题描述】:

我有以下 Cassandra 表

cqlsh:mydb> describe table events;

CREATE TABLE mydb.events (
    id uuid PRIMARY KEY,
    country text,
    insert_timestamp timestamp
) WITH bloom_filter_fp_chance = 0.01
    AND caching = '{"keys":"ALL", "rows_per_partition":"NONE"}'
    AND comment = ''
    AND compaction = {'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy'}
    AND compression = {'sstable_compression': 'org.apache.cassandra.io.compress.LZ4Compressor'}
    AND dclocal_read_repair_chance = 0.1
    AND default_time_to_live = 0
    AND gc_grace_seconds = 864000
    AND max_index_interval = 2048
    AND memtable_flush_period_in_ms = 0
    AND min_index_interval = 128
    AND read_repair_chance = 0.0
    AND speculative_retry = '99.0PERCENTILE';
CREATE INDEX country_index ON mydb.events (country);
CREATE INDEX insert_timestamp_index ON mydb.events (insert_timestamp);

如您所见,索引已在insert_timestamp 列上创建。

我已经通过https://stackoverflow.com/a/18698386/3238864

我虽然以下是正确的查询

cqlsh:mydb> select * from events where insert_timestamp >= '2016-03-01 08:27:22+0000';
InvalidRequest: code=2200 [Invalid query] message="No secondary indexes on the restricted columns support the provided operators: 'insert_timestamp >= <value>'"

cqlsh:mydb> select * from events where insert_timestamp >= '2016-03-01 08:27:22+0000' ALLOW FILTERING;
InvalidRequest: code=2200 [Invalid query] message="No secondary indexes on the restricted columns support the provided operators: 'insert_timestamp >= <value>'"

但是,使用 country 列作为 WHERE 条件的查询确实有效。

cqlsh:mydb> select * from events where country = 'my';

id                                   | country | insert_timestamp
--------------------------------------+---------+--------------------------
53167d6a-e125-46ff-bacf-f5b267de0258 |      my | 2016-03-01 08:27:22+0000

知道为什么以时间戳为条件的查询不起作用吗?我的查询语法有什么问题吗?

【问题讨论】:

标签: cassandra


【解决方案1】:

知道为什么以时间戳为条件的查询不起作用吗?我的查询语法有什么问题吗?

原生 Cassandra 二级索引仅限于 = 谓词。要启用不等式谓词,您需要添加 ALLOW FILTERING 但它会执行 full cluster scan :-(

如果您可以等待几周,Cassandra 3.4 将发布新的 SASI 二级索引,该索引对于范围查询更加有效:https://github.com/apache/cassandra/blob/trunk/doc/SASI.md

【讨论】:

  • 这个答案非常有用,以至于我无法投票的朋友要求我投票以表示感谢:)
【解决方案2】:

cassandra 中的索引与关系数据库中的索引完全不同。不同之处之一是,根本不允许在 cassandra 索引中进行范围查询。通常,范围查询仅适用于集群键(如果使用 ByteOrderPartitioner,它也可以与分区键一起使用,但并不常见),这意味着您必须为潜在的查询模式仔细设计列族。已经有many discussions in StackOverflow for the same topic了。

要了解何时使用 cassandra 的索引(它是为非常具体的情况设计的)及其局限性,this 是一篇好文章,

【讨论】:

    【解决方案3】:

    对二级索引的直接查询仅支持 =、CONTAINS 或 包含关键限制。

    二级索引查询允许您限制返回的结果 使用 =、>、>=、

    因此,一旦您将ALLOW FILTERING 添加到其中,您的查询就会起作用。

    select * from events where insert_timestamp >= '2016-03-01 08:27:22+0000' ALLOW FILTERING;
    

    您在问题中提到的链接将时间戳列作为聚类键。因此它在那里工作。

    根据评论RangeQuery on secondary index is not alllowed upto 2.2.x version

    仅供参考: 当 Cassandra 必须执行二级索引查询时,它会联系所有节点,检查二级索引位于每个节点上的部分。 因此,在像时间戳这样的高基数列上具有索引被认为是 cassandra 中的反模式。 您应该考虑更改数据模型以适应您的查询。

    【讨论】:

    • 我执行ALLOW FILTERING 版本作为你的。但我仍然遇到同样的错误。
    【解决方案4】:

    使用 cequel ORM

        now = DateTime.now
        today = DateTime.new(now.year, now.month, now.day, 0, 0, 0, now.zone) 
        tommorrow = today + (60 * 60 * 24);
        MyObject.allow_filtering!.where("done_date" => today..tommorrow).select( "*" )
    

    对我有用。

    【讨论】:

      猜你喜欢
      • 2017-04-30
      • 2019-05-25
      • 1970-01-01
      • 2016-05-04
      • 2016-05-30
      • 2018-12-29
      • 1970-01-01
      • 2012-11-27
      • 2014-05-07
      相关资源
      最近更新 更多