2015-04-17 15 views
24

Angenommen, ich eine Spalte Familie:Wie funktionieren Sekundärindizes in Cassandra?

CREATE TABLE update_audit (
    scopeid bigint, 
    formid bigint, 
    time timestamp, 
    record_link_id bigint, 
    ipaddress text, 
    user_zuid bigint, 
    value text, 
    PRIMARY KEY ((scopeid, formid), time) 
) WITH CLUSTERING ORDER BY (time DESC) 

Mit zwei Sekundärindizes, wo record_link_id ein hoher Kardinalität Säule ist:

CREATE INDEX update_audit_id_idx ON update_audit (record_link_id); 

CREATE INDEX update_audit_user_zuid_idx ON update_audit (user_zuid); 

Nach meiner Kenntnis Cassandra wie so zwei versteckte Spalte Familien schaffen :

Cassandra Sekundärindizes werden als lokale Indizes implementiert und nicht wie Norma verteilt Ich Tabellen. Jeder Knoten speichert nur einen Index für die Daten, die er speichert.

Betrachten Sie die folgende Abfrage:

select * from update_audit where scopeid=35 and formid=78005 and record_link_id=9897; 
  1. Wie wird diese Abfrage ausführen 'unter der Haube' in Cassandra?
  2. Wie wirkt sich ein Spaltenindex mit hoher Kardinalität (record_link_id) auf seine Leistung aus?
  3. Wird Cassandra alle Knoten für die obige Abfrage berühren? Warum?
  4. Welche Kriterien werden zuerst ausgeführt, Basistabelle partition_key oder sekundärer Index partition_key? Wie wird Cassandra diese beiden Ergebnisse schneiden?
+0

Meine 2 Cent: Da Sie einen vollständigen Partitionsschlüssel angegeben haben, ist es nicht sinnvoll, alle Knoten abzufragen. Es sollte eindeutig nur einen Knoten abfragen, der für (35, 78005) verantwortlich ist. Aufgrund der Art, wie Cassandra entworfen wird, erwarte ich, dass es in Betracht zieht, die Anzahl der beteiligten Knoten als Priorität zu reduzieren. Angesichts dessen sollte der einzige involvierte Knoten wahrscheinlich schauen, wie viele Datensätze er hat (35, 78005) und wie viele es im Index für 'record_link_id = 9897' hat, und den schnellsten verwenden, um die Abfrage zu bedienen (was nicht der Fall ist). t notwendigerweise der kleinste, abhängig davon, ob der Index auch nach Primärschlüssel sortiert ist). –

+0

Meine Theorie scheint von http://docs.datastax.com/de/cql/3.0/cql/ddl/ddl_using_multiple_indexes.html –

+0

unterstützt zu werden, wenn dies der Weg ist, dann wird das Erstellen von Index über Spalten mit hoher Kardinalität die schnellste und bestes Datenmodell (wenn Sie den Partitionsschlüssel auch in Kriterien einschließen). – Aftab

Antwort

38
select * from update_audit where scopeid=35 and formid=78005 and record_link_id=9897; 

Wie die obige Abfrage wird intern in cassandra arbeiten?

Im Wesentlichen werden alle Daten für die Partition scopeid=35 und formid=78005 zurückgegeben werden, und dann durch den record_link_id Index gefiltert. Es sucht nach dem record_link_id-Eintrag für 9897 und versucht, Übereinstimmungen zu finden, die den Zeilen entsprechen, die mit scopeid=35 und formid=78005 zurückgegeben werden. Der Schnittpunkt der Zeilen für die Partitionsschlüssel und die Indexschlüssel wird zurückgegeben.

Wie der Index der hohen Kardinalitätsspalte (record_link_id) die Abfrageleistung für die obige Abfrage beeinflusst?

Indizes mit hoher Kardinalität erzeugen im Wesentlichen eine Zeile für (fast) jeden Eintrag in der Haupttabelle. Die Leistung ist beeinträchtigt, da Cassandra sequenzielle Lesevorgänge für Abfrageergebnisse ausführt. Eine Indexabfrage zwingt Cassandra im Wesentlichen dazu, zufällige Lesevorgänge durchzuführen. Wenn die Kardinalität Ihres indizierten Werts zunimmt, erhöht sich auch die Zeit, die benötigt wird, um den abgefragten Wert zu finden.

Wird cassandra alle Knoten für die obige Abfrage berühren? WARUM?

Nein, es sollte nur einen Knoten berühren, die für die scopeid=35 und formid=78005 Partition verantwortlich ist. Indizes werden ebenfalls lokal gespeichert, enthalten nur Einträge, die für den lokalen Knoten gültig sind.

Erstellung Index über High-Kardinalität Spalten werden die schnellste und beste Datenmodell hier

Das Problem ist, dass Ansatz skaliert nicht, und wird langsam sein, wenn update_audit eine große Datenmenge ist. MVP Richard Low hat einen großen Artikel über Sekundärindizes (The Sweet Spot For Cassandra Secondary Indexing) und insbesondere in diesem Punkt:

Wenn Ihre Tabelle deutlich größer als Erinnerung ist, eine Abfrage wäre sehr langsam, auch nur ein paar tausend Ergebnisse zurückzukehren. Die Rückgabe von möglicherweise Millionen von Benutzern wäre katastrophal, obwohl es sich um eine effiziente Abfrage handelt.

...

In der Praxis bedeutet dies die Indizierung am nützlichsten ist Zehner für die Rückkehr, vielleicht Hunderte von Ergebnissen. Denken Sie daran, wenn Sie als nächstes einen sekundären Index verwenden.

Jetzt hilft Ihr Ansatz der ersten Einschränkung durch eine bestimmte Partition (wie Ihre Partition sollte in den Speicher passen). Aber ich denke, die bessere Leistung wäre hier, einen Clustering-Schlüssel zu erstellen, statt sich auf einen sekundären Index zu verlassen.

bearbeiten

Wie auf niedrigen Kardinalität Index Index, wenn es Millionen von Nutzern selbst skaliert, wenn wir den Primärschlüssel

bieten Es wird davon abhängen, wie weit Ihre Reihen sind . Das Problem bei extrem niedrigen Kardinalitätsindizes ist, dass der Prozentsatz der zurückgegebenen Zeilen normalerweise größer ist. Betrachten Sie zum Beispiel eine users Tabelle mit mehreren Zeilen. Sie beschränken den Partitionsschlüssel in Ihrer Abfrage, aber es werden immer noch 10.000 Zeilen zurückgegeben. Wenn Ihr Index auf etwas wie gender steht, muss Ihre Abfrage etwa die Hälfte dieser Zeilen ausfiltern, was nicht gut funktioniert.

Sekundärindizes funktionieren am besten (aus Mangel an einer besseren Beschreibung) "Kardinalität der Mitte der Straße". Unter Verwendung des obigen Beispiels einer users breiten Tabelle sollte ein Index auf country oder state viel besser funktionieren als ein Index auf gender (unter der Annahme, dass die meisten dieser Benutzer nicht alle in demselben Land oder Staat leben).

+2

Gründlich und aufschlussreich wie immer. – phact

+0

Toll !, nichts mehr zu fragen. Danke. – Aftab

+0

Danke für die Einsicht! Wie funktioniert es, wenn der Index für niedrigen Kardinalitätsindex bei Millionen von Benutzern skaliert wird, auch wenn wir den Partitionsschlüssel in der Abfrage wie 'select * von users partitionkey = x und gender = 'M'angeben. Aus der Storage-Perspektive, die versteckte Spalte Familie auf Geschlecht, wird es nicht überlaufen? Wird es ein Problem verursachen, da es eine versteckte Spaltenfamilie durchsuchen muss, um das Ergebnis herauszufiltern? http://stackoverflow.com/questions/29659564/validating-row-at-client-side-better-than-secondary-index-with-whole-primary-key – pinkpanther

2

Abfrage mit nur sekundären Index ist auch möglich, in Cassandra 2.x

select * from update_audit wo record_link_id = 9897;

Dies hat jedoch große Auswirkungen auf das Abrufen von Daten, da es alle Partitionen in einer verteilten Umgebung liest. Die von dieser Abfrage abgerufenen Daten sind ebenfalls nicht konsistent und konnten nicht weitergeleitet werden.

Vorschlag:
Verwendung von Sekundärindex wird als DIRT Abfrage von NoSQL-Datenmodell-Ansicht sein.

Um Sekundärindex zu vermeiden, könnten wir eine neue Tabelle erstellen und Daten dorthin kopieren.Da es sich um eine Abfrage der Anwendung handelt, werden Tabellen aus Abfragen abgeleitet.