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

nao*_*omi 4 cql cassandra range-query secondary-indexes

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

我遵循了这三条建议:

  1. 使用ALLOW FILTERING
  2. 包括相等比较
  3. 在reading_value列上创建二级索引.

这是我的查询:

select * from todmorden_numeric where sensor_name = 'pHradio' and reading_value < 5  allow filtering;
Run Code Online (Sandbox Code Playgroud)

哪条信息被拒绝:

Bad Request: No indexed columns present in by-columns clause with Equal operator
Run Code Online (Sandbox Code Playgroud)

我尝试将一个辅助索引添加到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);
Run Code Online (Sandbox Code Playgroud)

ash*_*hic 8

Cassandra仅允许范围搜索:

a)分区密钥仅在使用ByteOrderPartitioner时(默认现在是murmur3).

b)任何单个聚类键只有在主键定义中的目标列已经由谓词中的=运算符指定之前定义的任何聚类键时.

它们不适用于二级指数.

请考虑以下表定义:

CREATE TABLE tod1 (name text, time timestamp, 
    val float, PRIMARY KEY (name, time));
Run Code Online (Sandbox Code Playgroud)

在这种情况下,你不能在val上做范围.

考虑一下这个:

CREATE TABLE tod2 (name text, time timestamp, 
    val float, PRIMARY KEY (name, time, val));
Run Code Online (Sandbox Code Playgroud)

那么以下是有效的:

SELECT * FROM tod2 WHERE name='X' AND time='timehere' AND val < 5; 
Run Code Online (Sandbox Code Playgroud)

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

SELECT * from tod2 WHERE name='X' AND val < 5; 
Run Code Online (Sandbox Code Playgroud)

它没有效果,因为您没有使用主键def中的先前聚类键(在本例中为时间)进行过滤.

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

CREATE TABLE tod3 (name text, time timestamp, 
    val float, PRIMARY KEY (name, val, time));
Run Code Online (Sandbox Code Playgroud)

请注意主键中列的顺序:val在时间之前.

这将允许您:

SELECT * from tod3 WHERE name='asd' AND val < 5;
Run Code Online (Sandbox Code Playgroud)

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

希望有所帮助.