2012-07-05 16 views
6

estoy usando Cassandra 1.1.2 Estoy tratando de convertir una aplicación de RDBMS a Cassandra. En mi solicitud RDBMS He siguiente tabla llamada tabla 1:Cassandra: Consulta con cláusula where contiene greather- o menor que (< and >)

| Col1 | Col2 | Col3 | Col4 | 
  1. Col1: String (clave principal)
  2. Col2: String (clave principal)
  3. Col3: BIGINT (índice)
  4. Col4 : Bigint

Esta tabla cuenta con más de 200 millones de discos. Parcialmente consulta utilizada es algo así como:

Select * from table where col3 < 100 and col3 > 50; 

En Cassandra utilicé siguiente instrucción para crear la tabla:

create table table1 (primary_key varchar, col1 varchar, 
col2 varchar, col3 bigint, col4 bigint, primary key (primary_key)); 

create index on table1(col3); 

me cambió la clave principal para una columna adicional (calculo la llave dentro de mi solicitud) . Después de importar algunos registros Traté de ejecutar siguiendo CQL:

select * from table1 where col3 < 100 and col3 > 50; 

Este resultado es:

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

La consulta seleccionar col1, col2, col3, col4 de tabla1 donde col3 = 67 obras

Google dijo que no hay manera de ejecutar ese tipo de consultas. ¿Está bien? ¿Algún consejo sobre cómo crear una consulta?

Respuesta

6

índices Cassandra en realidad no admiten el acceso secuencial; ver http://www.datastax.com/docs/1.1/ddl/indexes para una buena explicación rápida de dónde son útiles. Pero no te desesperes; la forma más clásica de usar Cassandra (y muchos otros sistemas NoSQL) es desnormalizar, desnormalizar, desnormalizar.

Se puede ser una buena idea en su caso, utilizar el patrón de cubo gama clásica, que le permite utilizar el RandomPartitioner recomendado y mantenga sus filas bien distribuidos en todo el clúster, al tiempo que permite el acceso secuencial a sus valores. La idea en este caso es hacer un segundo valor de col3 del mapeo de la familia de columnas dinámica (incluido y ordenado) a los valores primary_key relacionados. A modo de ejemplo, si sus col3 valores van de 0 a 10^9 y están bastante uniformemente distribuidos, es posible que desee para ponerlos en 1000 cubos de rango 10^6 cada uno (el mejor nivel de granularidad dependerá del tipo de consulta que necesidad, el tipo de datos que tiene, consultar el tiempo de ida y vuelta, etc.). Ejemplo de esquema para cql3:

CREATE TABLE indexotron (
    rangestart int, 
    col3val int, 
    table1key varchar, 
    PRIMARY KEY (rangestart, col3val, table1key) 
); 

Al insertar en table1, se debe insertar una fila correspondiente en indexotron, con rangestart = int(col3val/1000000). A continuación, cuando es necesario enumerar todas las filas de table1 con col3> X, necesita consultar hasta 1000 cubos de indexotron, pero todos los col3val s dentro se ordenarán.Ejemplo de consulta para encontrar todos table1.primary_key valores para los que table1.col3 < 4021:

SELECT * FROM indexotron WHERE rangestart = 0 ORDER BY col3val; 
SELECT * FROM indexotron WHERE rangestart = 1000 ORDER BY col3val; 
SELECT * FROM indexotron WHERE rangestart = 2000 ORDER BY col3val; 
SELECT * FROM indexotron WHERE rangestart = 3000 ORDER BY col3val; 
SELECT * FROM indexotron WHERE rangestart = 4000 AND col3val < 4021 ORDER BY col3val; 
+0

'select count (*)' podría ser útil también, FWIW ... – rogerdpack

0

Si col3 siempre se conoce pequeños valores/rangos, puede ser capaz de salirse con una tabla simple que también asigna de nuevo a la tabla inicial, por ejemplo:

create table table2 (col3val int, table1key varchar, 
    primary key (col3val, table1key)); 

y utilizar

insert into table2 (col3val, table1key) values (55, 'foreign_key'); 
insert into table2 (col3val, table1key) values (55, 'foreign_key3'); 
select * from table2 where col3val = 51; 
select * from table2 where col3val = 52; 
... 

Quizás bien si usted no tiene demasiado grande de las gamas. (¿Podría obtener el mismo efecto con su índice secundario también, pero los índices secundarios no son muy recomendables?). En teoría, podría paralelizarlo "localmente en el lado del cliente".

Parece que la "manera de Cassandra" es tener una clave como "ID de usuario" y la usa como la primera parte de "todas sus consultas", por lo que puede necesitar replantear su modelo de datos, entonces puede tener consultas como select * from table1 where userid='X' and col3val > 3 y puede work (asumiendo una clave de clúster en col3val).