2012-07-05 11 views
6

Sto usando Cassandra 1.1.2 Sto provando a convertire un'applicazione RDBMS in Cassandra. Nella mia applicazione RDBMS ho seguente tabella denominata Table1:Cassandra: query con clausola where maggiore o minore di (< and >)

| Col1 | Col2 | Col3 | Col4 | 
  1. Col1: String (chiave primaria)
  2. Col2: String (chiave primaria)
  3. Col3: bigint (index)
  4. Col4 : Bigint

Questa tabella conta oltre 200 milioni di record. Per lo più query utilizzata è qualcosa di simile:

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

In Cassandra ho usato seguente istruzione per creare la tabella:

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

create index on table1(col3); 

ho cambiato la chiave primaria per una colonna aggiuntiva (a calcolare la chiave dentro la mia applicazione) . Dopo l'importazione alcuni record ho provato ad eseguire seguente CQL:

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

Questo risultato è:

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

La query selezionare col1, col2, col3, col4 da table1 dove col3 = 67 opere

Google ha detto che non c'è modo di eseguire questo tipo di query. È giusto? Qualche consiglio su come creare una query di questo tipo?

risposta

6

Gli indici di Cassandra non supportano effettivamente l'accesso sequenziale; vedi http://www.datastax.com/docs/1.1/ddl/indexes per una buona spiegazione rapida di dove sono utili. Ma non disperare; il modo più classico di usare Cassandra (e molti altri sistemi NoSQL) è denormalizzare, denormalizzare, denormalizzare.

E può essere una buona idea nel tuo caso per utilizzare il modello di secchio-gamma classica, che consente di utilizzare il RandomPartitioner consigliato e mantenere i filari ben distribuiti in tutto il cluster, pur consentendo l'accesso sequenziale ai vostri valori. In questo caso, l'idea è quella di creare un secondo valore dinamico di mappatura delle colonne (con o senza ordine) col3 ai relativi valori primary_key. Ad esempio, se i tuoi valori col3 sono compresi tra 0 e 10^9 e sono distribuiti in modo abbastanza uniforme, potresti volerli inserire in 1000 intervalli di intervallo 10^6 ciascuno (il livello migliore di granularità dipenderà dal tipo di query che hai bisogno, il tipo di dati che hai, interrogare il tempo di andata e ritorno, ecc.). schema di esempio per cql3:

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

Quando si inseriscono in table1, si deve inserire una riga corrispondente indexotron, con rangestart = int(col3val/1000000). Quindi, quando è necessario enumerare tutte le righe in table1 con col3> X, è necessario interrogare fino a 1000 intervalli di indexotron, ma tutti gli col3val s verranno ordinati.query di esempio per trovare tutti table1.primary_key valori per i quali 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 (*)' potrebbe essere utile pure, FWIW ... – rogerdpack

0

Se col3 è sempre noto piccoli valori/intervalli, si può essere in grado di cavarsela con un tavolo più semplice che associa anche tornare al tavolo iniziale, es:

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

e utilizzare

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; 
... 

Forse OK se non si dispone di troppo grande degli intervalli. (si potrebbe ottenere lo stesso effetto anche con l'indice secondario, ma gli indici secondari non sono altamente raccomandati?). Potrebbe teoricamente parallelizzarlo "localmente sul lato client".

Sembra che "Cassandra way" abbia una chiave come "userid" e la usi come prima parte di "tutte le tue query", quindi potresti aver bisogno di ripensare il tuo modello di dati, quindi puoi avere domande come select * from table1 where userid='X' and col3val > 3 e può work (presupponendo una chiave di cluster su col3val).

Problemi correlati