使用C#在Cassandra中批量插入

时间:2019-05-04 12:07:49

标签: c# cassandra cql

我是卡桑德拉的新人。我必须使用c#在cassandra中一次性插入50000行。我正在使用cassandra c#驱动程序。我正在使用以下代码插入 cassandra中的数据。请帮助我

string tableName = "" + ConfigurationManager.AppSettings["tableName"];
            string keySpace = "test";// "" + ConfigurationManager.AppSettings["Keyspace"];
            //string query = "INSERT INTO " + tableName + " (emp_name, emp_position,emp_firstname,uniqueid) VALUES (?, ?,?,?)"; //; "SELECT * FROM "+ tableName + " limit 2 ";
            string query = string.Empty;
            query =
"BEGIN BATCH " +
"INSERT INTO " + tableName + " (emp_name, emp_position,emp_firstname,uniqueid) VALUES (?, ?,?,?);" +
"INSERT INTO " + tableName + " (emp_name, emp_position,emp_firstname,uniqueid) VALUES (?, ?,?,?);" +
"INSERT INTO " + tableName + " (emp_name, emp_position,emp_firstname,uniqueid) VALUES (?, ?,?,?);" +
" APPLY BATCH";

BatchStatement(keySpace, query,
                    Convert.ToString("ashish" + i), 2, Convert.ToString("Mohan" + i), System.Guid.NewGuid(),
                    Convert.ToString("ashish" + i), 2, Convert.ToString("Mohan" + i), System.Guid.NewGuid(),
                    Convert.ToString("ashish" + i), 2, Convert.ToString("Mohan" + i), System.Guid.NewGuid()
public void BatchStatement(string keySpace, string query, params object[] parameter)
    {
        try
        {
            BatchStatement objBatchStatement = new BatchStatement();
            PreparedStatement statement = PrepareQueryStatement(keySpace, query);
            objBatchStatement.Add(statement.Bind(parameter));
            var session = cluster.Connect(keySpace);
            //objBatchStatement.ConsistencyLevel
            // Execute the batch
            //RowSet row = session.Execute(query);
            RowSet row = session.Execute(objBatchStatement);

        }
        catch (Exception ex)
            {
            Console.WriteLine("Excpetion occured during batch operation method Name BatchStatement error : " + ex.ToString());
        }

    }

我遇到错误:批处理语句无效:仅允许UPDATE,INSERT和DELETE语句。

2 个答案:

答案 0 :(得分:3)

我不太了解您的代码示例,因此不知道您是否在批处理中使用SELECT查询,这似乎是问题所在。无论如何,您可能会误用Batch,因为Cassandra中的批次用于原子性而非性能(在大多数情况下)。

如果要尽可能快地插入那50000行,则更快(并建议)与session.ExecuteAsync异步执行50000插入。 尝试这样的事情:

var tasks = new List<Task>();

foreach (BoundStatement query in queries) 
{
    tasks.Add(session.ExecuteAsync(query));
}

await Task.WhenAll(tasks).ConfigureAwait(false);

对于具有更多行要插入的更高级的用例,则可能有必要控制并发执行的请求数量,但是标准的任务并行库已经为您完成了其中的一些工作。

Batch比单独异步执行所有这些请求要快的唯一情况是,您可以使用属于同一分区的语句创建微批处理,但这很难完成,并且很可能您不需要性能提升。

更新

在您编辑问题之后,我可以理解代码示例。如果您仍然想使用Batch而不是我上面建议的方法,那么您要做的是:

var batch = new BatchStatement();
foreach (BoundStatement query in queries) 
{
    batch.Add(query); // you can also add SimpleStatements instead of BoundStatements
}

await session.ExecuteAsync(batch).ConfigureAwait(false);

答案 1 :(得分:1)

要回答特定问题...

批处理中的无效语句:仅允许UPDATE,INSERT和DELETE语句。

"BEGIN BATCH " +
...
" APPLY BATCH";

BEGIN BATCHAPPLY BATCH是不允许的语句。 BatchStatement对象会为您解决这个问题。

至此声明:

  

我必须在Cassandra中一次性插入50000行

João是绝对正确的,因为您正在做的是滥用Cassandra的BATCH功能。 BATCH(在Cassandra中)旨在将原子写入一次应用于多个表。它不是为支持对一个表的50000次写入而构建的。我看到开发人员团队在执行此操作时无意间导致群集节点崩溃。

之所以不起作用,是因为Cassandra意识到它没有一个单独的分区来发送批处理。因此,它选择了一个协调器节点,该节点负责从所有其他节点提取和组装50000个结果。该节点很快变得不知所措,并崩溃。

同样,João异步编写行的建议是解决之道。我唯一要进行的调整是添加一种机制来限制任何时间处于活动状态的线程数,以保护您的节点免受5万次背压写入的影响。