2013-07-15 16 views
10

Wie kann ich eine Reihe von Composite-Säulen mit CQL3 ziehen?Iterating durch Cassandra breite Reihe mit CQL3

sich das folgende:

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

In Cassandra Was dies effektiv macht, ist erzeugt eine ColumnFamily mit ganzzahligen Reihen (Werte von a) und mit CompositeColumns zusammengesetzt aus den Werten von b und c und die Zeichenkette ‚d ". Natürlich ist dies alles von CQL3 verdeckt, so dass wir denken, dass wir in einzelne Datenbankzeilen einfügen ... aber ich schweife ab.

Und betrachte die folgenden Eingänge:

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'); 

In meinem aktuellen Anwendungsfall möchte ich alle Werte von Stuff lesen, n Werte zu einem Zeitpunkt. Wie mache ich das? Hier ist meine aktuellen Take mit n=4:

SELECT * FROM Stuff WHERE a=1 LIMIT 4; 

Und wie erwartet erhalte ich:

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

Das Problem, dass ich den Weg laufen wird, wie bekomme ich die nächsten 4? Hier ist mein Versuch:

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

Das funktioniert nicht, weil wir b gleich ‚A‘ gezwungen haben - was eine vernünftige Sache zu tun! Aber ich habe nichts in der CQL3-Syntax gefunden, das es mir erlaubt, weiter zu iterieren. Ich wünschte, ich könnte etwas tun wie:

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

Wie erreiche ich mein gewünschtes Ergebnis. Das heißt, wie kann ich CQL3 Rückkehr machen:

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

Hinweis an mich selbst: [jemand anders, der das gleiche Problem hat] (http://stackoverflow.com/q/16951532/348056). – JnBrymn

Antwort

5

Auto Funkruf https://issues.apache.org/jira/browse/CASSANDRA-4415 getan, es ist Release Cassandra 2.0.1

+4

Nur für mein Verständnis, Ich habe Cassnadra 2.0.6 installiert und Cqlsh verwendet Ich habe versucht, eine Select-Abfrage auf einer CF (die etwa 20K Datensätze hat) ohne Begrenzung, das Ergebnis meiner Abfrage ist 10K und zeigt eine Meldung "** Default LIMIT von 10000 war verwendet. Geben Sie Ihre eigene LIMIT-Klausel an, um mehr Ergebnisse zu erhalten. ** "..Wo ist dann die automatische Paginierung, oder ist das etwas falsches? – Shri

0

Was Sie versuchen zu tun ist, bekommen Paginierung Sachen in Cassandra. CQL3 unterstützt dies nicht. Sie sollten eine Spalte erstellen, die für einen Vergleich geeignet ist, d. H. Für weniger als, größer als Operationen, und diese Spalte sollte eine zunehmende/abnehmende Sequenz bilden. In der Tat, wie jorgebg oben bemerkte, würde die Verkettung von b + c dazu passen.

4

Nach dem Lesen durch CQL3 Dokument habe ich keine Möglichkeit gefunden, den gewünschten Effekt zu erzielen.

Sie können jedoch den gewünschten Effekt mit einer Reihe von CQL-Abfragen fälschen. Berücksichtigen Sie, dass ich die Elemente im obigen Modell 4 gleichzeitig durchsuchen möchte. Es ist leicht genug, die erste 4:

SELECT * FROM a = 1 LIMIT 4;

Allerdings gibt es keine Möglichkeit, die nächsten 4 in einer einzigen Abfrage zu erhalten. Aber ich kann es stückweise machen.Der letzte Punkt aus der obigen Abfrage ist

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

Also habe ich eine Abfrage kann von hier und bekommen alles bis zum nächsten Wert von b zu starten:

SELECT * FROM a = 1 WHERE b = 'A 'und c>' S 'GRENZE 4;

in diesem Fall und ich werde eine einzige CQL3 Reihe bekommen:

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

(Nun, wenn ich 4 Reihen bekommen habe, würde ich die Grenze erreicht, und ich würde beginnen beim nächsten Mal wieder mit dem letzten . Element dieses Satzes Aber jetzt habe ich nur eine Zeile) Also, um den Rest habe ich aus iterieren zu bekommen, dass Punkt und die restlichen drei Zeilen erhalten.

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

und ich weiter mit dem gleichen Algorithmus bis ich inkrementell so weit gescannt habe wie ich möchte.

Im obigen Beispiel besteht der PRIMARY KEY aus 3 Elementen, was bedeutet, dass unter CQL in Cassandra die Spaltennamen CompositeColumns aus 2 Elementen sind (... naja, im Grunde genommen spielt der Unterschied hier keine Rolle). Und da die CompositeColumns aus zwei Elementen bestehen, müssen Sie zwei Abfragen durchführen, wie ich hier demonstriert habe. Wenn der PRIMARY KEY jedoch aus n Elementen besteht, müssen Sie n-1 Abfragen erstellen, um einen Scan der CQL-Tabelle (a.k.a Cassandra-Zeile) zu fälschen.


Update: Tatsächlich hat CQL3 keine Server-Cursor hat, (siehe „CQL3 Paginierung“ Abschnitt here), und wenn Sie zu fälschen wollen, würden Sie etwas oben beschrieben verwenden (Lesen Sie weiter über diesen Link, so sehen Sie meine Grundidee, die vom Autor des Beitrags ausgearbeitet wurde).

Es gibt jedoch eine JIRA issue in Bezug auf den Server-Cursor, die in Cassandra 2 verfügbar sein wird und die bereits in Cassandra 2 Beta vorhanden ist.

Es gibt auch eine verwandte JIRA issue, die es viel einfacher machen würde, den clientseitigen Cursor zu implementieren, wie ich oben angedeutet habe. Aber es steht ungelöst.


Update2: JIRA issue ist nun behoben.

können Sie jetzt Abfrage mit Tupel/Vektor-Syntax WHERE (c1, c2)> (1, 0)

+0

Ich empfehle die Verwendung der LIMIT-Klausel nicht. Verwenden Sie stattdessen Ihre Primärschlüssel, vielleicht mit Hilfe einer Meta-Tabelle. Ich erlebe starke Leistungseinbrüche, was vermutlich auf die Natur verteilter Datenbanken zurückzuführen ist - da es eine konzertierte Anstrengung braucht, um festzustellen, wann die LIMIT erreicht ist, muss jemand alle Zeilen zählen, bevor er die Ergebnismenge zurückgibt. – omnibear

-1

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

+0

Im Allgemeinen sind Antworten viel hilfreicher, wenn sie eine Erklärung enthalten, was der Code tun soll, und warum das Problem dadurch gelöst wird, ohne andere einzuführen. (Dieser Beitrag wurde von mindestens einem Benutzer gekennzeichnet, vermutlich weil er der Meinung war, dass eine Antwort ohne Erklärung gelöscht werden sollte.) –