错误com.websudos.phantom - 批量太大

时间:2016-04-05 22:44:45

标签: scala cassandra-2.1 phantom-dsl

我收到以下错误:

22:24:34.419 [run-main-0] DEBUG com.websudos.phantom - Executing query: com.datastax.driver.core.BatchStatement@3f4f5b68
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

每次重新运行代码并在以下时间点出现此错误:

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

 count
-------
 51728

(1 rows)

Warnings :
Aggregation query used without partition key

提前感谢任何见解。

+++ UPDATES +++

所以有问题的代码是

//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)

以下显示了Transaction的插入功能,Block也有类似的代码。

试图关注

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

&安培;&安培;

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

但我仍然在努力寻找一种不会导致Batch too large错误的实现。

//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)
  }

}

3 个答案:

答案 0 :(得分:2)

也许你误解了卡桑德拉批量的目的。

实际上,他们的原子性不是要运行多个查询,而是更快"。

可以在这里找到一个很好的解释:

https://lostechies.com/ryansvihla/2014/08/28/cassandra-batch-loading-without-the-batch-keyword/

答案 1 :(得分:2)

您获得的错误不是因为表的大小,而是因为批处理中的查询数量。在任何给定的批次中,您最多可以同时运行100个查询。

与此同时,你几乎99%的人在这里使用不太优化的方法,因为你从来没有真正想要在一个批次中进行这么多的查询。正如Thiago所说,批次的目的是保证原子性,而不是优化性能。

如果您只想进行并行查询,只需使用Future.sequence,它将使用fork join pool方法对操作进行并行化。

错误来自Cassandra ,而不是来自幻影。无论您在客户端使用何种方法,批量大小都有上限。

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

希望这有帮助!

<强>更新

假设您有一个交易清单。

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

这将产生一个将在所有基础期货完成时完成的未来,从而有效地为您提供原始Future[List[ResultSet]]的返回类型:List[Future[ResultSet]]

答案 2 :(得分:1)

正如其他人所说,您的第一条错误消息来自非常大的BATCH语句。正如您在传统关系数据库中所想到的那样,BATCH语句不是为批量插入而设计的。 BATCH语句仅在ATOMICALLY在几个非规范化表中插入数据或使用UNLOGGED BATCH在同一分区键下插入数据时才有用。

Batch statements should NOT be used as an optimization technique,因为它们不是为速度而设计的,实际上会损害您的表现。

最后,这是一条ERROR消息,因为Cassandra客户端驱动程序正在尝试保护群集免受非常大的BATCH语句的影响,该语句可以(并且将)关闭群集中的节点。

其次,你指出运行SELECT count(*) FROM table;会给你警告:

Aggregation query used without partition key

使用count(*)未指定分区键是antipattern。由于上述类似的原因,它可能会对群集的稳定性产生负面影响。

最后,我怀疑你的Cassandra DSL库中的某个地方(不熟悉Phantom-DSL)它正在进行你不期望的BATCH,或者你可能在没有完全理解它的适当用法的情况下有意识地使用BATCH。我知道在spring-data中,当你插入一个项目列表(这是一个可怕的反模式)时,它们会使用BATCH,这可能会导致类似的错误。