【问题标题】:Cassandra CQL range query rejected despite equality operator and secondary index尽管有相等运算符和二级索引,但 Cassandra CQL 范围查询被拒绝
【发布时间】:2014-09-13 16:30:12
【问题描述】:

从下面的表格架构中,我尝试选择所有低于 5 的 pH 读数。

我听从了这三条建议:

  1. 使用允许过滤
  2. 包括相等比较
  3. 在 reading_value 列上创建二级索引。

这是我的查询:

select * from todmorden_numeric where sensor_name = 'pHradio' and reading_value < 5  allow filtering;

此消息被拒绝:

Bad Request: No indexed columns present in by-columns clause with Equal operator

我尝试向 sensor_name 列添加二级索引,但被告知它已经是键的一部分,因此已经被索引。

我在表使用了一段时间后创建了索引 - 这可能是问题吗?我运行“nodetool refresh”,希望它能使索引可用,但这不起作用。这是describe table todmorden_numeric 的输出:

CREATE TABLE todmorden_numeric (
  sensor_name text,
  reading_time timestamp,
  reading_value float,
  PRIMARY KEY ((sensor_name), reading_time)
) WITH
  bloom_filter_fp_chance=0.010000 AND
  caching='KEYS_ONLY' AND
  comment='Data that suits being stored as floats' AND
  dclocal_read_repair_chance=0.000000 AND
  gc_grace_seconds=864000 AND
  index_interval=128 AND
  read_repair_chance=0.100000 AND
  replicate_on_write='true' AND
  populate_io_cache_on_flush='false' AND
  default_time_to_live=0 AND
  speculative_retry='99.0PERCENTILE' AND
  memtable_flush_period_in_ms=0 AND
  compaction={'class': 'SizeTieredCompactionStrategy'} AND
  compression={'sstable_compression': 'LZ4Compressor'};

CREATE INDEX todmorden_numeric_reading_value_idx ON todmorden_numeric (reading_value);

【问题讨论】:

    标签: cassandra cql secondary-indexes range-query


    【解决方案1】:

    Cassandra 只允许范围搜索:

    a) 仅当使用 ByteOrderPartitioner 时才使用分区键(现在默认为 murmur3)。

    b) 仅当在主键定义中的目标列之前定义的任何集群键已经由谓词中的 = 运算符指定时,才可以使用任何单个集群键。

    它们不适用于二级索引。

    考虑下面的表定义:

    CREATE TABLE tod1 (name text, time timestamp, 
        val float, PRIMARY KEY (name, time));
    

    在这种情况下,您不能对 val 进行范围设置。

    考虑这个:

    CREATE TABLE tod2 (name text, time timestamp, 
        val float, PRIMARY KEY (name, time, val));
    

    那么以下是有效的:

    SELECT * FROM tod2 WHERE name='X' AND time='timehere' AND val < 5; 
    

    有点无意义,但这是无效的:

    SELECT * from tod2 WHERE name='X' AND val < 5; 
    

    这是无效的,因为您没有在主键 def(在本例中为时间)中按先前的集群键进行过滤。

    对于您的查询,您可能希望这样做:

    CREATE TABLE tod3 (name text, time timestamp, 
        val float, PRIMARY KEY (name, val, time));
    

    注意主键中列的顺序:val's before time。

    这将允许您这样做:

    SELECT * from tod3 WHERE name='asd' AND val < 5;
    

    另一方面,您打算保留数据多长时间?你多久阅读一次?这可能会导致您的分区很快变得非常大。您可能希望将它的读数存储到多个分区中(手动分片)。也许每天一个分区?当然,这些事情很大程度上取决于您的访问模式。

    希望对您有所帮助。

    【讨论】:

    • 另外值得注意的是,您可以根据时间戳进行范围查询并将值加载到内存中,并聚合客户端。另一种选择是使用 Spark 之类的东西来进行后期聚合。
    • 感谢您的解释。我不知道 Cassandra 对于可以运行的查询有这么严格的限制。我来自 SQL 背景(我们不都是吗?)并且有很多东西要学!我选择了 Cassandra,因为它被推荐用于存储时间序列数据。我认为是时候进行架构审查了......我也会研究你关于分片的建议。
    • Cassandra 在用例方面非常灵活,但您确实需要进行一些数据建模。在处理 cassandra 时,您首先考虑您的查询和访问模式,而不是拥有数据并随意查询它(即使在 SQL 领域,这也可能对性能非常不利)。这是一个非常有趣的挑战,但是是的,还有一些东西需要学习。玩得开心:)
    猜你喜欢
    • 2016-06-13
    • 2023-04-08
    • 2015-03-10
    • 1970-01-01
    • 1970-01-01
    • 2013-01-02
    • 2013-08-14
    • 2015-11-09
    • 1970-01-01
    相关资源
    最近更新 更多