Cassandraの、batch_mutateには、map<key : string, map<column_family : string, list<Mutation>>>みたいな、引数を渡します。このMutationは、登録用のColumnリストか、削除用のDeletionオブジェクトを格納出来るようになっているので、同じカラムに対して、同時に登録と削除を指定することも出来るわけです。
では、実際に同時に指定すると、どうなるんでしょうか。削除されてから登録されるのか、登録されてから削除されるのか、実験してみました。
// *** 一部、CassandraemonのAPIを使用 *** //
var socket = new TSocket("localhost", 9160);
var protocol = new TBinaryProtocol(socket);
var client = new Cassandra.Client(protocol);
socket.Open();
// Insert用のMutation作成
var column = new ColumnOrSuperColumn
{
Column = new Column().SetNameValueTimestamp
(
"c1",
"10",
DateTime.Now.Ticks
)
};
var insertMutation = new Mutation { Column_or_supercolumn = column };
// Delete用のMutation作成
var deletion = new Deletion
{
Timestamp = DateTime.Now.Ticks,
Predicate = new SlicePredicate
{
Column_names = new List<byte[]>
{
"c1".ToCassandraByte()
}
}
};
var deleteMutation = new Mutation { Deletion = deletion };
// Insert → Delete順のMap
var map1 = new Dictionary<string, Dictionary<string, List<Mutation>>>()
{
{
"k1",
new Dictionary<string, List<Mutation>>()
{
{
"cf",
new List<Mutation>() { insertMutation, deleteMutation }
}
}
}
};
// Delete → Insert順のMap
var map2 = new Dictionary<string, Dictionary<string, List<Mutation>>>()
{
{
"k1",
new Dictionary<string, List<Mutation>>()
{
{
"cf",
new List<Mutation>() { deleteMutation, insertMutation }
}
}
}
};
// ColumnPathを作っとく
var path = new ColumnPath { Column_family = "cf", Column = "c1".ToCassandraByte() };
// Insert → Delete順のMapを実行して、データを取得してみる
client.batch_mutate("ks1", map1, ConsistencyLevel.ONE);
try
{
var CorS1 = client.get("ks1", "k1", path, ConsistencyLevel.ONE);
Console.WriteLine("Found.");
}
catch(NotFoundException)
{
Console.WriteLine("Not Found.");
}
// Delete → Insert順のMapを実行して、データを取得してみる
client.batch_mutate("ks1", map2, ConsistencyLevel.ONE);
try
{
var CorS1 = client.get("ks1", "k1", path, ConsistencyLevel.ONE);
Console.WriteLine("Found.");
}
catch(NotFoundException)
{
Console.WriteLine("Not Found.");
}
socket.Close();
/* result
Not Found.
Not Found.
*/
Mutationのリストに、登録用のMutationから突っ込んでも、削除用から突っ込んでも、結局は登録したカラムが削除されてしまっています。さらに、上記コードをFor文で囲って100回連続で実行しても、1回も登録の方が後に行われたケースはありませんでした。つまり、削除操作が必ず後で実行されるってことでしょうか。
ソースをちらっと見た感じでは特に順序制御とかしてないような感じだったんですが、削除がメチャクチャ遅いだけだったりして( ̄∇  ̄ ) たしか、Cassandraの削除はフラグを立てるだけだった気がするので、その辺の振る舞いが関係してたりもするのかも。なんにせよ、Updateの感覚でDelete→Insertとかしたいときは、操作を分ける必要があるってことですね。Cassandraemonの場合だと、DeleteOnSubmitのあと、一回SubmitChangesしてから、InsertOnSubmitみたいな手順になります、ご注意ください。
あ、あと、これはあくまで、バージョン0.6.2での結果なんで、他では変わるかもです。