开发者社区> 问答> 正文

如何实现分页查询?

如何实现分页查询?

展开
收起
保持可爱mmm 2020-03-29 15:38:46 756 0
1 条回答
写回答
取消 提交回答
  • 表格存储是一个分布式存储系统,对于查询请求的翻页(分页),有多种方式。本文详细为您介绍如何实现分页查询。 表 如果只有表,没有多元索引,可以通过以下办法翻页:

    使用next_token翻页:每次GetRange请求的Response中会有一个next_token,将这个next_token设置到下一次请求的Request中即可,这样就能实现连续翻页。
    使用GetRangeIterator迭代器,通过iterator.next()方法持续获取下一条数据。
    不支持offset跳页查询,如果业务需要,可以在客户端通过next_token或Iterator模拟。
    不支持获取整个范围的行数和总页数。
    

    多元索引

    如果创建了多元索引,则可以通过以下办法翻页:

    使用offset + limit方式:可以跳页,但是offset + limit最大值不能超过10000。如果超过,请使用第二种方法。
    使用next_token翻页,每次Search请求的Response中会有下一次的next_token,将这个next_token设置到下一次请求的Request中即可,这样就能实现连续翻页。
    使用SearchIterator迭代器,通过iterator.next()方法持续获取下一条数据。
    支持获取总行数,总行数除以limit就是总页数,需要在Request中设置getTotalCount为true,该选项打开后会增大资源消耗,所以性能会有所下降。
    

    表示例

    下面是一个实现分页读接口的示例代码,提供offset过滤以及读取指定页数的数据。

    /** * 范围查询指定范围内的数据,返回指定页数大小的数据,并能根据offset跳过部分行。 */ private static Pair<List , RowPrimaryKey> readByPage(OTSClient client, String tableName, RowPrimaryKey startKey, RowPrimaryKey endKey, int offset, int pageSize) { Preconditions.checkArgument(offset >= 0, "Offset should not be negative."); Preconditions.checkArgument(pageSize > 0, "Page size should be greater than 0."); List rows = new ArrayList (pageSize); int limit = pageSize; int skip = offset; RowPrimaryKey nextStart = startKey; // 若查询的数据量很大,则一次请求有可能不会返回所有的数据,需要流式查询所有需要的数据。 while (limit > 0 && nextStart != null) { // 构造GetRange的查询参数。 // 注意:startPrimaryKey需要设置为上一次读到的位点,从上一次未读完的地方继续往下读,实现流式的范围查询。 RangeRowQueryCriteria criteria = new RangeRowQueryCriteria(tableName); criteria.setInclusiveStartPrimaryKey(nextStart); criteria.setExclusiveEndPrimaryKey(endKey); // 需要设置正确的limit,这里期望读出的数据行数最多为完整的一页数据以及需要过滤(offset)的数据 criteria.setLimit(skip + limit); GetRangeRequest request = new GetRangeRequest(); request.setRangeRowQueryCriteria(criteria); GetRangeResult response = client.getRange(request); for (Row row : response.getRows()) { if (skip > 0) { skip--; // 对于offset之前的数据,需要过滤掉,采用的策略是读出来后在客户端进行过滤。 } else { rows.add(row); limit--; } } // 设置下一次查询的起始位点 nextStart = response.getNextStartPrimaryKey(); } return new Pair<List , RowPrimaryKey>(rows, nextStart); }

    下面是使用以上接口,顺序地按页读取某个指定范围内的所有数据。

    private static void readByPage(OTSClient client, String tableName) { int pageSize = 8; int offset = 33; RowPrimaryKey startKey = new RowPrimaryKey(); startKey.addPrimaryKeyColumn(COLUMN_GID_NAME, PrimaryKeyValue.INF_MIN); startKey.addPrimaryKeyColumn(COLUMN_UID_NAME, PrimaryKeyValue.INF_MIN); RowPrimaryKey endKey = new RowPrimaryKey(); endKey.addPrimaryKeyColumn(COLUMN_GID_NAME, PrimaryKeyValue.INF_MAX); endKey.addPrimaryKeyColumn(COLUMN_UID_NAME, PrimaryKeyValue.INF_MAX); // 读第一页,从范围的offset=33的行开始读起 Pair<List , RowPrimaryKey> result = readByPage(client, tableName, startKey, endKey, offset, pageSize); for (Row row : result.getKey()) { System.out.println(row.getColumns()); } System.out.println("Total rows count: " + result.getKey().size()); // 顺序翻页,读完范围内的所有数据 startKey = result.getValue(); while (startKey != null) { System.out.println("============= start read next page =============="); result = readByPage(client, tableName, startKey, endKey, 0, pageSize); for (Row row : result.getKey()) { System.out.println(row.getColumns()); } startKey = result.getValue(); System.out.println("Total rows count: " + result.getKey().size()); } }

    2020-03-29 15:43:15
    赞同 展开评论 打赏
问答地址:
问答排行榜
最热
最新

相关电子书

更多
MySQL查询优化实战 立即下载
低代码开发师(初级)实战教程 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载