提高Cassandra和Java集合的性能

我们在项目中使用NoSQL(Cassandra)。 我们有一个表A(5000条记录),这是一个主表。 我们有另一张表B(2000条记录)。 表B有4列,表A有25列。 我们公开了一个REST服务来获取B的所有记录; 喜欢/ service / getB。 此服务将返回6列作为响应 –

{ "result": [ { "col1FromB": "1B", "col2FromB": "2B", "col3FromB": "3B", "col4FromB": "4B", "col1FromA": "1A", "col2FromA": "2A" }, { "col1FromB": "11B", "col2FromB": "12B", "col3FromB": "13B", "col4FromB": "14B", "col1FromA": "11A", "col2FromA": "12A" } ] } 

因此,对于表B中的每个项目,都会查询表A.这就是我这样做的方式 –

  //Get all from Table B (took 90 ms in Local and 30 ms in Test) Select select = QueryBuilder.select().from("B"); List bList = cassandraOperations.select(select, B.class); //Loop through bList and do a lookup using id in Table A (took 46000 ms (46 sec) in Local (horrible) and 6000 ms (6 sec) in Test) For(B b: bList) { Select select = QueryBuilder.select(“col1FromA”, “col2FromA”).from("A"); select.where(QueryBuilder.eq(“id”, b.getId())); A a = cassandraOperations.selectOne(select, A.class); ---- ---- //Prepare final Pojo with a and b objects and add into a List and return } 

因此,在本地环境中查找时间非常高,在测试环境中也非常不好。 我所使用的只是Java集合。

有没有办法让它变得更好,以便我们在较短的时间内获得记录。

 For(B b: bList) { Select select = QueryBuilder.select(“col1FromA”, “col2FromA”).from("A"); select.where(QueryBuilder.eq(“id”, b.getId())); A a = cassandraOperations.selectOne(select, A.class); 

此代码在每次迭代中执行阻塞请求cassandraOperations.selectOne ,这意味着每次下一次迭代都必须等待前一次迭代。 所有2000个请求将一个接一个地执行很长一段时间。

为了避免这种情况,使用异步方式获取循环中的记录(如我所见,您正在使用Spring,selectOne可以替换为selectOneAsynchronously ,返回ResultSetFuture,将这些未来保存在某些列表中,并在所有请求都使用时检索记录发送)。

Cassandra根据分区键在其节点上分发数据。 它保证分区中的所有行(具有相同分区键的一组行)位于同一节点上,使得完整或部分分区的SELECT语句非常快。

如果您有一个查询来拉下多个分区,那么每个分区可能位于不同的节点上,导致选择期间的网络流量将导致性能下降。 通过添加第二个表,您正在复杂化问题。

在Cassandra中,您应该查看您的查询,然后在可能的情况下为每个查询创建一个表。 当您接受数据复制并避免连接时,Cassandra数据模型可以提高性能。

因此,我将创建一个新表,将查询数据预先连接到一个名为C的表中。当您在A中编写数据时,您将其写入A和C,当您将数据写入B时,您将其写入B和C.如果可能,您希望将要在同一分区中查询的数据放在一起。 如果每次调用该端点时都要下拉整个数据集,您可能需要考虑对表中的所有数据使用单个分区键(因为您的数据量相对较少),这将保证您读取表格,整个读取将脱离单个节点。

我想你在本地机器上看到了良好的性能,因为你的查询没有进入网络。