如何在Cassandra中批量插入多行数据

21

什么是在Cassandra列族中插入多行的最有效方法?是否可以在单个调用中完成这个操作。

目前,我的方法是添加并插入多个列,然后执行。在单个调用中,我正在持久化一行数据。我正在寻找一个批量插入的策略。


你使用的是哪个驱动程序?你在使用CQL吗?你使用的是哪个Cassandra版本? - Richard
Cassandra的版本是1.2.x,我正在使用Hector API。 - ajjain
5个回答

36

CQL包含一个BEGIN BATCH...APPLY BATCH语句,允许您将多个插入分组,以便开发人员可以创建和执行一系列请求 (请参见http://www.datastax.com/dev/blog/client-side-improvements-in-cassandra-2-0)。

以下代码在Scala中可行:

PreparedStatement ps = session.prepare(
"BEGIN BATCH" +    
"INSERT INTO messages (user_id, msg_id, title, body) VALUES (?, ?, ?, ?);" +    
"INSERT INTO messages (user_id, msg_id, title, body) VALUES (?, ?, ?, ?);" +    
"INSERT INTO messages (user_id, msg_id, title, body) VALUES (?, ?, ?, ?);" +    
"APPLY BATCH" ); 

session.execute(ps.bind(uid, mid1, title1, body1, uid, mid2, title2, body2, uid, mid3, title3, body3));

如果您事先不知道要执行哪些语句,您可以使用以下语法(Scala):

var statement: PreparedStatement = session.prepare("INSERT INTO people (name,age) VALUES (?,?)")
var boundStatement = new BoundStatement(statement)
val batchStmt = new BatchStatement()
batchStmt.add(boundStatement.bind("User A", "10"))
batchStmt.add(boundStatement.bind("User B", "12"))
session.execute(batchStmt)

注意: BatchStatement 只能容纳最多 65536 条语句。我通过艰难的经历学会了这一点。 :-)


@user853509 一条帮助了你的“好答案”,都没有获得一个赞?太严厉了。 - Aaron
好答案。我给你点赞。 - Aaron
在Scala示例中,所有的var都应该是val。对象引用不会改变。 - mlg
2
后面的版本对我不起作用。必须将每个 boundStatement.bind(...) 替换为 new BoundStatement(statement).bind(...) - oseiskar
我测试了两种方法。第一种对于插入操作来说比第二种快大约4倍,尽管我绑定了1500个参数。 - omikron
显示剩余3条评论

6

4
在Cassandra中有一个批量插入操作。你可以将插入操作批处理在一起,即使是在不同的列族中,以使插入更加高效。
在Hector中,您可以使用 HFactory.createMutator 然后使用返回的 Mutator 上的 add 方法添加操作到您的批处理中。当准备好时,调用 execute()
如果您正在使用 CQL,则可以通过使用 BEGIN BATCH 开始批处理并使用 APPLY BATCH 结束来将内容分组到批处理中。

4
请确保您明白何时使用批处理是一个好主意,何时不是(请参阅http://docs.datastax.com/en/cql/3.1/cql/cql_using/useBatch.html)。通常情况下,批处理并不能提高性能,甚至在最坏情况下会降低性能。如果您不需要原子写入,请务必使用未记录的批处理。 - rs_atl
2
好观点。我认为在 thrift 批处理中几乎总是有帮助的(因为 thrift 的开销非常大)。在 CQL 中,您应该使用异步插入和预准备语句而不是批处理。除了插入都在同一个分区的情况外,在这种情况下,批处理更有效率。 - Richard

1

当尝试插入多行数据时,数据库连接的往返时间可能成为性能瓶颈。在这种情况下,我们通常需要一种方式来避免等待一个INSERT完成,以便我们可以开始下一个INSERT。目前据我所知有两种方法:

  • 如果数据一致性很重要,请使用LOGGED BATCH,但是如this question所说,BATCH并不一定在所有情况下都能提高性能。
  • 否则,在Cassandra客户端库中使用异步API,例如在Python中有一个execute_async方法。

此外,您可以在执行SQL语句之前准备好该语句。我还没有测试过准备语句与普通插入的整体性能。但我认为,如果有数千个INSERT或更多,则应该获得性能提升。


1

1
请问您能否修复上面的Datastax URL?目前它返回404错误。 - realPK

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接