使用 Datastax 驱动程序 3.6 的 Cassandra 分页:不支持空分页状态和获取大小

Cassandra Pagination Using Datastax driver 3.6: Null paging state and fetch size not honoured

我们正在尝试制作一个 returns 从 cassandra 数据库分页结果的应用程序 UI。

UI 会将 fetchSizepagingState 传递给我们的 API 并基于此我们将 return List<MyObject>size=fetchSize。如果传递 pagingState 我们将从最后一页恢复查询(如 cassandra 文档中所述:https://docs.datastax.com/en/developer/java-driver/3.6/manual/paging/

请注意,我使用的是 Cassandra 驱动程序版本 3.6。

但是当我们实现这个时,Cassandra 总是 return 数据库中的所有条目忽略提取大小,这反过来导致 ResultSet.getExecutionInfo().getPagingState() 的值 null。我该如何解决?

我在数据库中为 MyObject 创建了 16 条记录,并尝试将提取大小传递为 5 以获取它们。所有 16 条记录都具有相同的分区键 ID-1.

// Util method to invoke Statement. "session" is cassandra session 

public static ResultSet execute(int pageSize, Statement statement, String pageState) { 
    if (isVoid(pageSize)) {
        pageSize=-1;
    }
    statement.setFetchSize(pageSize);
    if (!isVoid(pageState)) {
        statement.setPagingState(PagingState.fromString(pageState));
    }
    return session.execute(statement);
}

// Accesor interface method for my query that returns a Statement 
object

@Query("SELECT * FROM " + MY_TABLE + " WHERE id=:id")
Statement getAll(@Param("id") String id);

// Main Code returning list of MyObject that has an object Mapper -> 
//mapper 
Statement statement=accessor.getAll("ID1");
ResultSet rs=execute(5,statement,null );
List<MyObject> list=mapper.map(rs).all();
String pageState=rs.getExecutionInfo().getPagingState();

在上面的代码中,我希望 Cassandra return 包含 5 个 MyObject 对象的列表,并为我的 pageState 变量提供一个字符串值。 两者都没有按预期工作。

列表的大小为 16(基本上它获取了所有记录) 由于以上原因,pageStatenull,因为所有记录都已提取。

我在这里错过了什么?

编辑: 根据观察 ResultSet 将遵循语句中传递的 fetchSize,但是当我们使用 all() 方法将其映射到 List<MyObject> 时,它会获取数据库中的所有结果(大小 = Cluster wide fetchSize) . 因此,当我调用 Result#one 方法 5(= pageSize) 次并将它们推送到列表中时,我得到了分页状态以及页面大小的结果。

上述示例 Util 方法

public static <T> List<T> getPaginatedList(ResultSet resultSet, Mapper<T> mapper,int pageSize) {
    List<T> entities=new ArrayList<>();
    Result<T> result=mapper.map(resultSet);
    IntStream.range(1,pageSize).forEach(i->{
        entities.add(result.one());
    });
    return entities;
}

这对性能有何影响?

如您所见,尽管您指定了 setFetchSize,但您得到所有​​结果的原因是因为获取大小只是设置了每个请求页面的请求大小。当您调用 all() 时,驱动程序会透明地翻阅所有结果。

all() 相比,单独调用 one() 不会对性能产生影响,但是我建议更改您使用页面的逻辑,因为我预计 IntStream.range(1, pageSize) 在以下情况下会失败您已经耗尽了结果集(即您将提取大小设置为 500,但只有 495 行)。相反,您可以使用 IntStream.range(1, resultSet.getAvailableWithoutFetching()).

您也可以选择遍历结果集直到 ResultSet.isExhausted() returns true 以防止获取下一页。