同步SELECT + INSERT与INSERT之间的性能差异...如果不是CQL中的EXISTS?

时间:2015-09-15 23:34:51

标签: cassandra cql cql3

我有一个CQL表(cql 3,cassandra 2.0。*),它看起来像:

CREATE TABLE IF NOT EXISTS user_things (
   user_id bigint,
   thing_id bigint,
   created_at timeuuid,
  PRIMARY KEY (user_id, thing_id)
);

我想做一个像

这样的插入
INSERT INTO user_things (user_id, thing_id, created_at) VALUES (?, ?, now())

但仅限于该行不存在。

我可以在两个同步语句中执行此操作(首先是SELECT,如果SELECT没有返回一行,则返回INSERT)或者我可以使用INSERT ... IF NOT EXISTS。

CQL docs州“但请注意,使用IF NOT EXISTS将产生不可忽略的性能成本(内部使用Paxos),因此应谨慎使用。”

我想知道是否有人做过基准测试,看看如果我们有很多这样的操作发生了什么更有效率? (比如数百秒)

2 个答案:

答案 0 :(得分:6)

这在很大程度上取决于您使用的拓扑结构。如果将其限制为本地数据中心(使用LOCAL_SERIAL)并使用较小的复制因子,则IF NOT EXISTS非常快。如果您尝试在多个数据中心或更高的复制因子中使用它,那么它会显着减慢。有一个开放的ticket来提高它的性能,所以希望很快就能完成,因为它目前是一个过于昂贵的操作,有很多往返。

另一个会降低IF NOT EXISTS的因素是在群集行上使用它时。当您的表只有复合分区键而没有聚类列时,它似乎工作得最快。

如果您在写入路线之前阅读,那么您还有其他问题需要处理。首先你会有一个竞争条件,因为如果两个客户在同一时间读取,然后两个都决定写一个,你会得到一个覆盖另一个,这种方式使得读取毫无意义(请参阅此处的另一种方法) :collision detection。如果你不注意竞争条件,并使用像ONE这样的低一致性来进行读写,那么它可能会胜过IF NOT EXISTS。

你必须为你的系统和架构对它进行基准测试,看看哪种情况在你的情况下更快。

答案 1 :(得分:0)

虽然我自己还没有完成基准测试,但我认为这两个同步语句的运行速度会更快,因为它只是做得不那么多。它正在执行两个设计良好的CQL查询,而另一个方法涉及节点之间至少4个通信“阶段”。

但是如果你确实使用这个方法,你是否能够保证这些查询是以原子方式执行的,并且在运行SELECT和运行INSERT之间的时间内不存在具有相同user_id和thing_id的INSERT?避免这种情况的需要是在Cassandra和Paxos中使用轻量级事务的驱动因素。