Consulta de rango de Cassandra CQL rechazada a pesar del operador de igualdad y el índice secundario
secondary-indexes range-query (1)
Desde el esquema de la tabla a continuación, estoy tratando de seleccionar todas las lecturas de pH que están por debajo de 5.
He seguido estos tres consejos:
- Use ALLOW FILTERING
- Incluir una comparación de igualdad
- Cree un índice secundario en la columna reading_value.
Aquí está mi consulta:
select * from todmorden_numeric where sensor_name = ''pHradio'' and reading_value < 5 allow filtering;
Que es rechazado con este mensaje:
Bad Request: No indexed columns present in by-columns clause with Equal operator
Intenté agregar un índice secundario a la columna sensor_name y me dijeron que ya era parte de la clave y, por lo tanto, ya estaba indexada.
Creé el índice después de que la mesa había estado en uso por un tiempo, ¿podría ser ese el problema? Ejecuté "nodetool refresh" con la esperanza de que el índice estuviera disponible pero esto no funcionó. Aquí está el resultado de la describe table todmorden_numeric
de 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 permite la búsqueda de rango solo en:
a) Partition Key solo si se usa ByteOrderPartitioner (el valor predeterminado ahora es murmur3).
b) cualquier tecla de agrupamiento SOLO SI las teclas de agrupamiento definidas ANTES de la columna de destino en la definición de clave primaria ya están especificadas por un operador = en el predicado.
No funcionan en índices secundarios.
Considere la siguiente definición de tabla:
CREATE TABLE tod1 (name text, time timestamp,
val float, PRIMARY KEY (name, time));
NO PUEDE hacer un rango en el val en este caso.
Considera este:
CREATE TABLE tod2 (name text, time timestamp,
val float, PRIMARY KEY (name, time, val));
Entonces, lo siguiente es válido:
SELECT * FROM tod2 WHERE name=''X'' AND time=''timehere'' AND val < 5;
Un poco inútil, pero esto no es válido:
SELECT * from tod2 WHERE name=''X'' AND val < 5;
No es válido ya que no se ha filtrado por una clave de clúster anterior en la definición de la clave principal (en este caso, el tiempo).
Para su consulta, es posible que desee hacer esto:
CREATE TABLE tod3 (name text, time timestamp,
val float, PRIMARY KEY (name, val, time));
Tenga en cuenta el orden de las columnas en la clave principal: val''s before time.
Esto te permitirá hacer:
SELECT * from tod3 WHERE name=''asd'' AND val < 5;
En una nota diferente, ¿cuánto tiempo tiene la intención de mantener los datos? ¿Con qué frecuencia obtienes lecturas? Esto puede hacer que su partición crezca bastante rápidamente. Es posible que desee dividir las lecturas en varias particiones (fragmentación manual). Tal vez una partición por día? Por supuesto, tales cosas dependerían en gran medida de tus patrones de acceso.
Espero que ayude.