全部产品
存储与CDN 数据库 安全 应用服务 数加·人工智能 数加·大数据基础服务 互联网中间件 视频服务 开发者工具 解决方案 物联网
表格存储

多行数据操作

更新时间:2017-06-07 13:26:11

表格存储的 SDK 提供了 BatchGetRow、BatchWriteRow、GetRange 和 createRangeIterator 等多行操作的接口。

批量读(BatchGetRow)

批量读接口可以一次请求读取多行数据,参数与 GetRow 接口参数一致。需要注意的是,批量读取的所有行采用相同的参数条件,比如 ColumnsToGet=[colA], 则要读取的所有行都只读取 colA 这一列。

与 BatchWriteRow 接口类似,使用 BatchGetRow 接口时也需要检查返回值。存在部分行失败,而不抛出异常的情况,此时失败行的信息在 BatchGetRowResponse 中。可以通过 BatchGetRowResponse#getFailedRows 方法获取失败的行的信息,通过 BatchGetRowResponse#isAllSucceed 方法可以判断是否所有行都获取成功。

示例

读取 10 行,设置版本条件、要读取的列、过滤器等。

  1. private static void batchGetRow(SyncClient client) {
  2. MultiRowQueryCriteria multiRowQueryCriteria = new MultiRowQueryCriteria(TABLE_NAME);
  3. // 加入10个要读取的行
  4. for (int i = 0; i < 10; i++) {
  5. PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
  6. primaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString("pk" + i));
  7. PrimaryKey primaryKey = primaryKeyBuilder.build();
  8. multiRowQueryCriteria.addRow(primaryKey);
  9. }
  10. // 添加条件
  11. multiRowQueryCriteria.setMaxVersions(1);
  12. multiRowQueryCriteria.addColumnsToGet("Col0");
  13. multiRowQueryCriteria.addColumnsToGet("Col1");
  14. SingleColumnValueFilter singleColumnValueFilter = new SingleColumnValueFilter("Col0",
  15. SingleColumnValueFilter.CompareOperator.EQUAL, ColumnValue.fromLong(0));
  16. singleColumnValueFilter.setPassIfMissing(false);
  17. multiRowQueryCriteria.setFilter(singleColumnValueFilter);
  18. BatchGetRowRequest batchGetRowRequest = new BatchGetRowRequest();
  19. // batchGetRow支持读取多个表的数据, 一个multiRowQueryCriteria对应一个表的查询条件, 可以添加多个multiRowQueryCriteria.
  20. batchGetRowRequest.addMultiRowQueryCriteria(multiRowQueryCriteria);
  21. BatchGetRowResponse batchGetRowResponse = client.batchGetRow(batchGetRowRequest);
  22. System.out.println("是否全部成功:" + batchGetRowResponse.isAllSucceed());
  23. if (!batchGetRowResponse.isAllSucceed()) {
  24. for (BatchGetRowResponse.RowResult rowResult : batchGetRowResponse.getFailedRows()) {
  25. System.out.println("失败的行:" + batchGetRowRequest.getPrimaryKey(rowResult.getTableName(), rowResult.getIndex()));
  26. System.out.println("失败原因:" + rowResult.getError());
  27. }
  28. /**
  29. * 可以通过createRequestForRetry方法再构造一个请求对失败的行进行重试.这里只给出构造重试请求的部分.
  30. * 推荐的重试方法是使用SDK的自定义重试策略功能, 支持对batch操作的部分行错误进行重试. 设定重试策略后, 调用接口处即不需要增加重试代码.
  31. */
  32. BatchGetRowRequest retryRequest = batchGetRowRequest.createRequestForRetry(batchGetRowResponse.getFailedRows());
  33. }
  34. }

批量写(BatchWriteRow)

BatchWriteRow 接口可以在一次请求中进行批量的写入操作,写入操作包括 PutRow、UpdateRow 和 DeleteRow,也支持一次对多张表进行写入。

构造单个操作的过程与使用 PutRow 接口、UpdateRow 接口和 DeleteRow 接口时相同,也支持设置更新条件。

调用 BatchWriteRow 接口时,需要特别注意的是检查返回值。因为是批量写入,可能存在部分行成功部分行失败的情况,此时失败行的 Index 及错误信息在返回的 BatchWriteRowResponse 中,而并不抛出异常。可通过 BatchWriteRowResponse 的 isAllSucceed 方法判断是否全部成功。若不检查,可能会忽略掉部分操作的失败。另一方面,BatchWriteRow 接口也是可能抛出异常的。比如,服务端检查到某些操作出现参数错误,可能会抛出参数错误的异常,在抛出异常的情况下该请求中所有的操作都未执行。

示例

一次 BatchWriteRow 请求,包含 2 个 PutRow 操作,1 个 UpdateRow 操作,1 个 DeleteRow 操作。

  1. private static void batchWriteRow(SyncClient client) {
  2. BatchWriteRowRequest batchWriteRowRequest = new BatchWriteRowRequest();
  3. // 构造rowPutChange1
  4. PrimaryKeyBuilder pk1Builder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
  5. pk1Builder.addPrimaryKeyColumn(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString("pk1"));
  6. RowPutChange rowPutChange1 = new RowPutChange(TABLE_NAME, pk1Builder.build());
  7. // 添加一些列
  8. for (int i = 0; i < 10; i++) {
  9. rowPutChange1.addColumn(new Column("Col" + i, ColumnValue.fromLong(i)));
  10. }
  11. // 添加到batch操作中
  12. batchWriteRowRequest.addRowChange(rowPutChange1);
  13. // 构造rowPutChange2
  14. PrimaryKeyBuilder pk2Builder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
  15. pk2Builder.addPrimaryKeyColumn(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString("pk2"));
  16. RowPutChange rowPutChange2 = new RowPutChange(TABLE_NAME, pk2Builder.build());
  17. // 添加一些列
  18. for (int i = 0; i < 10; i++) {
  19. rowPutChange2.addColumn(new Column("Col" + i, ColumnValue.fromLong(i)));
  20. }
  21. // 添加到batch操作中
  22. batchWriteRowRequest.addRowChange(rowPutChange2);
  23. // 构造rowUpdateChange
  24. PrimaryKeyBuilder pk3Builder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
  25. pk3Builder.addPrimaryKeyColumn(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString("pk3"));
  26. RowUpdateChange rowUpdateChange = new RowUpdateChange(TABLE_NAME, pk3Builder.build());
  27. // 添加一些列
  28. for (int i = 0; i < 10; i++) {
  29. rowUpdateChange.put(new Column("Col" + i, ColumnValue.fromLong(i)));
  30. }
  31. // 删除一列
  32. rowUpdateChange.deleteColumns("Col10");
  33. // 添加到batch操作中
  34. batchWriteRowRequest.addRowChange(rowUpdateChange);
  35. // 构造rowDeleteChange
  36. PrimaryKeyBuilder pk4Builder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
  37. pk4Builder.addPrimaryKeyColumn(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString("pk4"));
  38. RowDeleteChange rowDeleteChange = new RowDeleteChange(TABLE_NAME, pk4Builder.build());
  39. // 添加到batch操作中
  40. batchWriteRowRequest.addRowChange(rowDeleteChange);
  41. BatchWriteRowResponse response = client.batchWriteRow(batchWriteRowRequest);
  42. System.out.println("是否全部成功:" + response.isAllSucceed());
  43. if (!response.isAllSucceed()) {
  44. for (BatchWriteRowResponse.RowResult rowResult : response.getFailedRows()) {
  45. System.out.println("失败的行:" + batchWriteRowRequest.getRowChange(rowResult.getTableName(), rowResult.getIndex()).getPrimaryKey());
  46. System.out.println("失败原因:" + rowResult.getError());
  47. }
  48. /**
  49. * 可以通过createRequestForRetry方法再构造一个请求对失败的行进行重试.这里只给出构造重试请求的部分.
  50. * 推荐的重试方法是使用SDK的自定义重试策略功能, 支持对batch操作的部分行错误进行重试. 设定重试策略后, 调用接口处即不需要增加重试代码.
  51. */
  52. BatchWriteRowRequest retryRequest = batchWriteRowRequest.createRequestForRetry(response.getFailedRows());
  53. }
  54. }

范围读(GetRange)

范围读取接口用于读取一个范围内的数据。表格存储表中的行都是按照主键排序的,而主键是由全部主键列按照顺序组成的,所以不能理解为表格存储会按照某列主键排序,这是常见的误区。

GetRange 接口支持按照给定范围正序读取和反序读取,可以限定要读取的行数。如果范围较大,已经扫描的行数或者数据量超过一定限制,会停止继续扫描,返回已经获取的行和下一个主键的位置。用户可以根据返回的下一个主键位置,继续发起请求,获取范围内剩余的行。

GetRange 请求的主要参数如下:

  • Direction:枚举类型,包括 FORWARD、BACKWARD,分别代表正序、反序。

  • InclusiveStartPrimaryKey:范围的起始主键(包含)。若为反序,起始主键要大于结束主键。

  • ExclusiveEndPrimaryKey:范围的结束主键(不包含)。若为反序,起始主键要大于结束主键。

  • Limit:本次请求返回的最大行数。

  • ColumnsToGet:要读取的列的集合。若不设置,则读取所有列。

  • MaxVersions:最多读取多少个版本。MaxVersions 与 TimeRange 必须至少设置一个。

  • TimeRange: 要读取的版本号的范围。MaxVersions 与 TimeRange 必须至少设置一个。

  • Filter:过滤器。过滤器在服务端对读取的结果再进行一次过滤。

示例

正序读取,判断 NextStartPrimaryKey 是否为 null,读取完范围内的全部数据。

  1. private static void getRange(SyncClient client, String startPkValue, String endPkValue) {
  2. RangeRowQueryCriteria rangeRowQueryCriteria = new RangeRowQueryCriteria(TABLE_NAME);
  3. // 设置起始主键
  4. PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
  5. primaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString(startPkValue));
  6. rangeRowQueryCriteria.setInclusiveStartPrimaryKey(primaryKeyBuilder.build());
  7. // 设置结束主键
  8. primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
  9. primaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString(endPkValue));
  10. rangeRowQueryCriteria.setExclusiveEndPrimaryKey(primaryKeyBuilder.build());
  11. rangeRowQueryCriteria.setMaxVersions(1);
  12. System.out.println("GetRange的结果为:");
  13. while (true) {
  14. GetRangeResponse getRangeResponse = client.getRange(new GetRangeRequest(rangeRowQueryCriteria));
  15. for (Row row : getRangeResponse.getRows()) {
  16. System.out.println(row);
  17. }
  18. // 若nextStartPrimaryKey不为null, 则继续读取.
  19. if (getRangeResponse.getNextStartPrimaryKey() != null) {
  20. rangeRowQueryCriteria.setInclusiveStartPrimaryKey(getRangeResponse.getNextStartPrimaryKey());
  21. } else {
  22. break;
  23. }
  24. }
  25. }

迭代读(createRangeIterator)

迭代读取数据。

示例

  1. private static void getRangeByIterator(SyncClient client, String startPkValue, String endPkValue) {
  2. RangeIteratorParameter rangeIteratorParameter = new RangeIteratorParameter(TABLE_NAME);
  3. // 设置起始主键
  4. PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
  5. primaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString(startPkValue));
  6. rangeIteratorParameter.setInclusiveStartPrimaryKey(primaryKeyBuilder.build());
  7. // 设置结束主键
  8. primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
  9. primaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME, PrimaryKeyValue.fromString(endPkValue));
  10. rangeIteratorParameter.setExclusiveEndPrimaryKey(primaryKeyBuilder.build());
  11. rangeIteratorParameter.setMaxVersions(1);
  12. Iterator<Row> iterator = client.createRangeIterator(rangeIteratorParameter);
  13. System.out.println("使用Iterator进行GetRange的结果为:");
  14. while (iterator.hasNext()) {
  15. Row row = iterator.next();
  16. System.out.println(row);
  17. }
  18. }
本文导读目录