2016-01-09 13 views
16

Ich habe einen Java-Client, der Datensätze (INSERT) im Stapel in Cassandra-Cluster schiebt. Die Elemente im Stapel haben alle denselben Zeilenschlüssel, sodass sie alle im selben Knoten platziert werden. Außerdem brauche ich die Transaktion nicht atomar, also habe ich ungeplant Batch verwendet.Was ist das Batch-Limit in Cassandra?

Die Anzahl der INSERT-Befehle in jedem Stapel hängt von verschiedenen Faktoren ab, kann aber zwischen 5 und 50000 liegen. Zuerst habe ich so viele Befehle wie in einem Batch eingegeben und übergeben. Dies warf com.datastax.driver.core.exceptions.InvalidQueryException: Batch too large. Dann verwendete ich eine Kappe von 1000 INSERT pro Batch und dann bis zu 300. Ich bemerkte, dass ich nur zufällig rate, ohne genau zu wissen, woher diese Grenze kommt, die Probleme auf der Straße verursachen kann.

Meine Frage ist, was ist das Limit? Kann ich es ändern? Wie kann ich wissen, wie viele Elemente in einem Stapel platziert werden können? Wann ist meine Charge "voll"?

Antwort

17

Ich würde empfehlen, die Kappe nicht zu erhöhen und nur in mehrere Anfragen aufzuteilen. Wenn man alles in eine einzige große Anfrage stellt, wird das den Koordinator erheblich beeinträchtigen. Wenn Sie alles in einer Partition haben, können Sie den Durchsatz einiger Chargen verbessern, indem Sie die Latenz reduzieren, aber die Chargen sollten nie zur Verbesserung der Leistung verwendet werden. Der Versuch, den maximalen Durchsatz zu optimieren, indem verschiedene Losgrößen verwendet werden, hängt weitgehend von Use-Case/Schema/Nodes ab und erfordert spezifische Tests, da es im Allgemeinen eine Klippe gibt, deren Größe sich zu verschlechtern beginnt.

Es gibt eine

# Fail any batch exceeding this value. 50kb (10x warn threshold) by default. 
batch_size_fail_threshold_in_kb: 50 

Option in Ihrem cassandra.yaml sie zu erhöhen, aber sicher sein, um zu testen, dass Ihr tatsächlich helfen und nicht zu verletzen Sie Durchsatz sind.

+0

Das ist, was ich für dank suchen. Wissen Sie, wie Sie die Größe des Stapels im Client am besten überwachen können? –

+2

Abhängig von der Treiber, den Sie verwenden, aber in der Java-Treiber können Sie getValues ​​() auf jede einzelne Anweisung in Batch verwendet werden, die ein Array von ByteBuffers zurückgibt, für die Sie die verbleibende() -Methode verwenden, können die Größe zu erhalten die Puffer einzeln und summieren sie alle zusammen, aber generell würde ich das nicht empfehlen. Sie sollten erschaffen super große Chargen nicht, gerade groß genug, wo man das Gefühl, dass Sie nicht einmal annähernd nahe an dieser Grenze. –

+0

gut gibt es paar Dinge hier. C * predigt Design durch Spalte anstelle von Zeilen und C * sagt 2B Spalten pro Partition aber empirisch wissen wir, die Sweet-Spot 100MB ist.Also selbst mit 100MB Partition und wenn die Standardgröße eines Stapels 50KB ist, ist das wie 100MB/50KB = 3125 Anfragen, um eine 100MB Partition abzurufen, also viel zu viele Anfragen. – user1870400

2

am Cassandra Blick loggt Sie in der Lage sein werden, Dinge zu entdecken wie:

ERROR 19.54.13 Batch für [Spiele] ist der Größe 103.072KiB, überschreiten spezifizierten Schwellenwert von 50.000KiB um 53.072KiB. (Siehe batch_size_fail_threshold_in_kb)

0

läuft über ein ähnliches Problem in Java, hier ist ein funktionales Beispiel dafür, wie Batch-Chargen:

import com.datastax.driver.core.BatchStatement; 
import com.datastax.driver.core.PreparedStatement; 
import com.datastax.driver.core.Session; 
import com.google.common.collect.Lists; 

import java.util.Collection; 
import java.util.stream.Collectors; 

public class CassandraBatchOfBatchesExample { 

    private final PreparedStatement statement; 
    private final Session session; 
    private final int batchSize; 

    public CassandraBatchOfBatchesExample(Session session, int batchSize) { 
     this.session = session; 
     this.batchSize = batchSize; 
     statement = session.prepare("INSERT_INTO some_table JSON ?"); 
    } 

    public void execute(Collection<String> jsons) { 
     Lists.partition(jsons 
       .stream() 
       .map(statement::bind) 
       .collect(Collectors.toList() 
      ), batchSize).stream() 
      .map(statements -> new BatchStatement().addAll(statements)) 
      .forEach(session::execute); 
    } 
} 

batchSize Variable benötigt, basierend auf der Größe der einzelnen Datensätze ändern eingeführt wird.