【问题标题】:Cassandra Pagination Using Datastax driver 3.6: Null paging state and fetch size not honoured使用 Datastax 驱动程序 3.6 的 Cassandra 分页:不支持 Null 分页状态和获取大小
【发布时间】:2019-10-27 20:45:12
【问题描述】:

我们正在尝试创建一个从 cassandra db 为 UI 返回分页结果的应用程序。

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

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

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

我在我的数据库中为 MyObject 创建了 16 条记录,并尝试将 fetch size 传递为 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 返回一个包含 5 个MyObject 对象的列表,并为我的pageState 变量提供一个字符串值。 两者都没有按预期工作。

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

我在这里错过了什么?

编辑: 从观察来看,ResultSet 将尊重语句中传递的 fetchSize,但是当我们使用all() 方法将其映射到List&lt;MyObject&gt; 时,它会获取数据库中的所有结果(大小 = 集群范围的 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;
}

这对性能有什么影响?

【问题讨论】:

    标签: java android cassandra datastax-java-driver


    【解决方案1】:

    正如您所看到的,尽管您指定了setFetchSize,但您得到所有​​结果的原因是因为 fetch size 只是设置了每个请求页面的请求大小。当您调用 all() 时,驱动程序会透明地对所有结果进行分页。

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

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

    【讨论】:

    • "getAvailableWithoutFetching()" -> 这将获取当前结果集中的获取计数(大小= pageSize),还是获取大小=集群范围获取大小的实体计数?如果上述情况属实,这将不会以线性(或更差)时间获取计数,对吧?
    • 在内部调用 ArrayDeque 上的 .size(),这是一个恒定时间操作(实际上是 O(1))
    猜你喜欢
    • 2016-06-11
    • 2016-11-29
    • 2015-03-12
    • 2017-03-16
    • 2019-10-26
    • 1970-01-01
    • 2022-08-10
    • 2018-04-24
    • 2017-06-25
    相关资源
    最近更新 更多