尽管存在相等运算符和二级索引,但Cassandra CQL范围查询被拒绝

时间:2014-07-22 17:52:42

标签: cassandra cql secondary-indexes range-query

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

我遵循了以下三条建议:

  1. 使用ALLOW FILTERING
  2. 包含相等比较
  3. 在reading_value列上创建二级索引。
  4. 这是我的问题:

    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列,并被告知它已经是密钥的一部分,因此已经编入索引。

    我在表使用一段时间后创建了索引 - 这可能是问题吗?我跑了&#34; nodetool refresh&#34;希望它能使索引可用,但这不起作用。以下是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);
    

1 个答案:

答案 0 :(得分:8)

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。

这样你就可以:

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

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

希望有所帮助。