2013-07-15 5 views
10

Come posso inserire un intervallo di colonne Composite con CQL3?Iterazione attraverso Cassandra wide row con CQL3

consideri il seguente:

CREATE TABLE Stuff (
    a int, 
    b text, 
    c text, 
    d text, 
    PRIMARY KEY (a,b,c) 
); 

In Cassandra ciò che fa efficacemente è crea un ColumnFamily con righe interi (valori di a) e CompositeColumns composto dai valori di B e C e la stringa letterale 'd '. Ovviamente tutto questo è coperto da CQL3 in modo tale che si possa pensare a che stiamo inserendo in singole righe del database ... ma sto divagando.

e considerare la seguente serie di ingressi:

INSERT INTO Stuff (a,b,c,d) VALUES (1,'A','P','whatever0'); 
INSERT INTO Stuff (a,b,c,d) VALUES (1,'A','Q','whatever1'); 
INSERT INTO Stuff (a,b,c,d) VALUES (1,'A','R','whatever2'); 
INSERT INTO Stuff (a,b,c,d) VALUES (1,'A','S','whatever3'); 
INSERT INTO Stuff (a,b,c,d) VALUES (1,'A','T','whatever4'); 
INSERT INTO Stuff (a,b,c,d) VALUES (1,'B','P','whatever5'); 
INSERT INTO Stuff (a,b,c,d) VALUES (1,'B','Q','whatever6'); 
INSERT INTO Stuff (a,b,c,d) VALUES (1,'B','R','whatever7'); 
INSERT INTO Stuff (a,b,c,d) VALUES (1,'B','S','whatever8'); 
INSERT INTO Stuff (a,b,c,d) VALUES (1,'B','T','whatever9'); 

Nel mio caso d'uso corrente, voglio leggere tutti i valori di roba, n valori alla volta. Come faccio a fare questo? Ecco il mio prendere corrente utilizzando n=4:

SELECT * FROM Stuff WHERE a=1 LIMIT 4; 

E come previsto ottengo:

a | b | c | d 
---+---+---+----------- 
1 | A | P | whatever0 
1 | A | Q | whatever1 
1 | A | R | whatever2 
1 | A | S | whatever3 

Il problema che ho incontrato è come faccio a ottenere il prossimo 4? Qui è il mio tentativo:

SELECT * FROM Stuff WHERE a=1 AND b='A' AND c>'S' LIMIT 4; 

Questo non funziona perché siamo costretti B alla parità di 'A' - che è una cosa ragionevole da fare! Ma non ho trovato nulla nella sintassi di CQL3 che mi permetta di continuare ad iterare comunque. Vorrei poter fare qualcosa di simile:

SELECT * FROM Stuff WHERE a=1 AND {b,c} > {'A','S'} LIMIT 4; 

Come posso raggiungere il mio risultato desiderato. Vale a dire, come faccio a restituire CQL3:

a | b | c | d 
---+---+---+----------- 
1 | A | T | whatever0 
1 | B | P | whatever1 
1 | B | Q | whatever2 
1 | B | R | whatever3 
+0

Nota per sé: [qualcun altro che ha lo stesso problema] (http://stackoverflow.com/q/16951532/348056). – JnBrymn

risposta

5

Auto paging è fatto https://issues.apache.org/jira/browse/CASSANDRA-4415, è il rilascio di Cassandra 2.0.1

+4

Solo per la mia comprensione, ho installato Cassnadra 2.0.6 e usando cqlsh ho provato a fare una query di selezione su un CF (che ha circa 20K di record) senza dare limiti, il risultato della mia query è 10K e visualizza un messaggio "** Il limite di default di 10000 è stato utilizzato. Specifica la tua clausola LIMIT per ottenere più risultati. ** "..Allora dov'è l'auto-impaginazione, o è qualcosa che non sto facendo/capisco. – Shri

0

Quello che si tenta di fare è ottenere materiale di impaginazione in Cassandra. CQL3 non supporta questo. Dovresti creare una colonna che sia adatta per il confronto, cioè per meno di, maggiore di operazioni e questa colonna dovrebbe formare una sequenza crescente/decrescente. In effetti, come notato in precedenza da jorgebg, la concatenazione di b + c si adatterebbe a questo.

4

Dopo aver letto il documento CQL3 non ho trovato un modo per ottenere l'effetto desiderato.

È tuttavia possibile simulare l'effetto desiderato con una serie di query CQL. Considera che voglio sfogliare gli elementi del modello precedente 4 alla volta. È abbastanza facile ottenere i primi 4:

SELEZIONA * DA a = 1 LIMIT 4;

Tuttavia non c'è modo di ottenere i successivi 4 in una singola query. Ma posso farlo a pezzetti.L'ultimo elemento dalla query di cui sopra è

a | b | c | d 
---+---+---+----------- 
1 | A | S | whatever3 

modo che io possa emettere una query per iniziare da qui e ottenere tutto fino al prossimo valore b:

SELECT * FROM a = 1 dove B = 'A 'e c>' S 'LIMIT 4;

E in questo caso prendo una singola riga CQL3:

a | b | c | d 
---+---+---+----------- 
1 | A | T | whatever4 

(Ora, se io avevo ottenuto 4 righe, mi ha colpito il limite e vorrei iniziare la prossima volta con l'ultimo . elemento di quel set, ma per ora non mi resta che una riga) Quindi, per ottenere il resto ho iterare da che punto e ottenere i restanti 3 righe:.

SELECT * FROM a = 1 WHERE b > 'A' LIMIT 3; 

e continuo con questo stesso algoritmo fino a quando non ho digitalizzato in modo incrementale quanto mi pare.

Nell'esempio sopra il PRIMARY KEY è composto da 3 elementi che significano che sotto CQL in Cassandra i nomi delle colonne sono CompositeColumns di 2 elementi (... in pratica, ma la differenza non conta qui). E poiché le colonne Composite sono di 2 elementi devi fare 2 query come ho dimostrato qui. In generale, tuttavia, se la PRIMARY KEY è degli elementi n, sarà necessario effettuare le query n-1 per simulare una scansione della tabella CQL (a.k.a riga Cassandra).


Aggiornamento: In effetti, CQL3 non ha un cursore sul lato server, (vedere la sezione "CQL3 impaginazione" here), e se si voleva fingere, dovreste usare qualcosa descritto in precedenza (leggi oltre su questo link, quindi vedi la mia idea di base elaborata dall'autore del post).

Tuttavia, esiste un JIRA issue relativo al cursore sul lato server che sarà disponibile in Cassandra 2 e che è già presente in Cassandra 2 Beta.

C'è anche un relativo JIRA issue che renderebbe molto più semplice implementare il cursore sul lato client come ho accennato sopra. Ma rimane irrisolto.


Aggiornamento2: JIRA issue ora corretto.

È ora possibile query utilizzando tuple/sintassi vettore WHERE (c1, c2)> (1, 0)

+0

Non è consigliabile utilizzare la clausola LIMIT. Usa invece le tue chiavi primarie, magari con l'aiuto di un meta-tavolo. Ho riscontrato gravi calo delle prestazioni, che presumo sia dovuto alla natura dei database distribuiti, poiché è necessario uno sforzo concertato per determinare quando viene raggiunto il LIMIT, qualcuno deve contare tutte le righe prima di restituire il set di risultati. – omnibear

-1

select * from stuff where a = 1 and (b,c) > ('A','S') limit 4;

+0

In genere, le risposte sono molto più utili se includono una spiegazione di ciò che il codice è destinato a fare e perché questo risolve il problema senza introdurre gli altri. (Questo post è stato contrassegnato da almeno un utente, presumibilmente perché pensava che una risposta senza spiegazione dovesse essere eliminata). –