使用 Datastax 驱动程序 3.6 的 Cassandra 分页:不支持空分页状态和获取大小
Cassandra Pagination Using Datastax driver 3.6: Null paging state and fetch size not honoured
我们正在尝试制作一个 returns 从 cassandra 数据库分页结果的应用程序 UI。
UI 会将 fetchSize
和 pagingState
传递给我们的 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(基本上它获取了所有记录)
由于以上原因,pageState
是 null
,因为所有记录都已提取。
我在这里错过了什么?
编辑:
根据观察 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 以防止获取下一页。
我们正在尝试制作一个 returns 从 cassandra 数据库分页结果的应用程序 UI。
UI 会将 fetchSize
和 pagingState
传递给我们的 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(基本上它获取了所有记录)
由于以上原因,pageState
是 null
,因为所有记录都已提取。
我在这里错过了什么?
编辑:
根据观察 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 以防止获取下一页。