2016-04-05 10 views
1

Ich erhalte die folgende Fehlermeldung:ERROR com.websudos.phantom - Batch zu groß

22:24:34.419 [run-main-0] DEBUG com.websudos.phantom - Executing query: [email protected] 
22:24:34.426 [pool-15-thread-3] ERROR com.websudos.phantom - Batch too large 
[error] (run-main-0) com.datastax.driver.core.exceptions.InvalidQueryException: Batch too large 
com.datastax.driver.core.exceptions.InvalidQueryException: Batch too large 

Haben Sie den Code erneut ausführen und immer diese Fehlermeldung auf dem folgenden Punkt jedes Mal: ​​

cqlsh> select count(*) from superchain.blocks limit 1000000; 

count 
------- 
51728 

(1 rows) 

Warnings : 
Aggregation query used without partition key 

Vielen Dank im Voraus für alle Einsichten.

+++ AKTUELL +++

So der säumige Code ist

//This file is Database.scala 
class Database(val keyspace: KeySpaceDef) extends DatabaseImpl(keyspace) { 
    def insertBlock(block: Block) = { 
    //should note here that have also tried Batch.unlogged to same effect 
    Batch.logged 
     .add(ChainDatabase.block.insertNewRecord(block)) 
     .future() 
    } 

    def insertTransaction(tx: Transaction) = { 
    //should note here that have also tried Batch.unlogged to same effect 
    Batch.logged 
     .add(ChainDatabase.tx.insertNewTransaction(tx)) 
     .future() 
    } 

    object block extends BlockTable with keyspace.Connector 

    object tx extends TransactionTable with keyspace.Connector 


} 

object ChainDatabase extends Database(Config.keySpaceDefinition) 

Im Folgenden werden die Einführungs Funktionen für Transaktion zeigt, und es gibt einen ähnlichen Code für den Block.

Haben

https://medium.com/@foundev/cassandra-batch-loading-without-the-batch-keyword-40f00e35e23e#.7zdd0qopv

& &

https://github.com/outworkers/phantom/wiki/Batch-statements

Aber bin immer noch kämpfen, zu folgen versucht, eine Implementierung zu finden, die den Batch too large Fehler nicht führen.

//This file is Transaction.scala 
abstract class TransactionTable extends TransactionColumnFamily with RootConnector { 

    override val tableName = "transactions" 

    def insertNew(tx: Transaction): Future[ResultSet] = insertNewTransaction(tx).future() 

    def insertNewTransaction(tx: Transaction) = { 
    insert 
     .value(_.txid, tx.txid) 
     .value(_.version, tx.version) 
     .value(_.locktime, tx.locktime) 
     .value(_.vout, tx.vout) 
     .value(_.vin, tx.vin) 
    } 

} 

Antwort

2

Der Fehler, den Sie bekommen ist nicht wegen der Größe der Tabelle, sondern auch wegen der Anzahl der Abfragen im Stapel. Sie können maximal 100 Abfragen gleichzeitig in einem bestimmten Stapel ausführen.

Gleichzeitig verwenden Sie fast 99% den weniger optimalen Ansatz hier, da Sie nie wirklich so viele Abfragen in einem einzelnen Stapel möchten. Thiago schlägt vor, dass Chargen so konstruiert sind, dass sie die Atomarität garantieren und nicht die Leistung optimieren.

Wenn Sie einfach parallel Abfragen ausführen möchten, verwenden Sie einfach Future.sequence, die einen Ansatz der Fork Join Pool verwenden, um die Operationen paralellisieren.

Der Fehler ist von Cassandra, nicht von Phantom. Es spielt keine Rolle, welche Art von Ansatz Sie auf dem Client verwenden, die Batch-Größe ist begrenzt.

// Assuming you have a list of queries: 
val execution = Future.sequence(queries map (_.future()) 

Hoffe, das hilft!

aktualisieren

Angenommen, Sie haben eine Liste von Transaktionen.

val list: List[Transaction] = .. 
// all you need is 
Future.sequence(list.map(tr => database.transactionTable.insertNew(tr)) 

Dies wird eine Zukunft produzieren, die abgeschlossen wird, wenn alle zugrunde liegenden Futures vollständig, effektiv Sie einen Rückgabetyp geben: Future[List[ResultSet]] von Ihrem ursprünglichen List[Future[ResultSet]].

+0

@ thiago-pereira & flavian: haben die Frage einige mehr in den Hoffnungen ein spezifisches Beispiel von "Wenn Sie einfach parallel Abfragen durchführen möchten, verwenden Sie einfach Future.sequence, die einen fork join Pool Art von Ansatz zu verwenden paralellisieren die Operationen. " –

1

Wie andere schon gesagt haben, stammt Ihre erste Fehlermeldung von einer BATCH-Anweisung, die sehr groß ist. BATCH-Anweisungen sind nicht für Batch-Einsätze gedacht, wie Sie es von einer traditionellen relationalen Datenbank erwarten würden. BATCH-Anweisungen sind nur beim ATOMISCHEN Einfügen von Daten über mehrere denormalisierte Tabellen oder beim Verwenden von UNLOGGED BATCH zum Einfügen von Daten unter demselben Partitionsschlüssel nützlich.

Batch statements should NOT be used as an optimization technique, da sie nicht für Geschwindigkeit ausgelegt sind und tatsächlich Ihre Leistung beeinträchtigen werden.

Am Ende ist dies eine Fehlermeldung, da der Cassandra Client Driver versucht, den Cluster vor einer sehr großen BATCH-Anweisung zu schützen, die Knoten in Ihrem Cluster zum Absturz bringen kann.

Zweitens weisen Sie darauf hin, dass eine SELECT count(*) FROM table; läuft geben Sie die Warnung:

Aggregation query used without partition key.

Verwenden count(*) ist ohne Angabe eines Partitionsschlüssels ist ein antipattern. Aus ähnlichen Gründen wie oben kann es die Stabilität Ihres Clusters beeinträchtigen.

Schließlich vermute ich irgendwo in Ihrer Cassandra DSL-Bibliothek (nicht mit Phantom-DSL vertraut), dass es einen BATCH macht, wo Sie es nicht erwarten, oder Sie bewusst BATCH verwenden, ohne es richtig zu verstehen. Ich weiß, dass sie in Frühlingsdaten einen BATCH verwenden, wenn Sie eine Liste von Items einfügen (was ein schreckliches Antipattern ist), was zu einem ähnlichen Fehler führen könnte.