Table Store提供了BatchGetRow,BatchWriteRow和GetRange等多行操作的接口。

说明 以下操作为同步接口的示例,异步接口的操作请参见异步接口

批量读(BatchGetRow)

批量读取一个或多个表中的若干行数据。

BatchGetRow操作可视为多个GetRow操作的集合,各个操作独立执行,独立返回结果,独立计算服务能力单元。与执行大量的GetRow操作相比,使用BatchGetRow操作可以有效减少请求的响应时间,提高数据的读取速率。

BatchGetRow可能出现以下两种错误:

  • 请求整体错误,比如网络错误。这类错误存放在batchGetRow()的返回值里。
  • 请求整体没有错误,但个别行出错。这类错误存放在相应的行的结果里。

示例

BatchGetRowRequest req;
{
    MultiPointQueryCriterion& criterion = req.mutableCriteria().append();
    IVector<MultiPointQueryCriterion::RowKey>& rowkeys = criterion.mutableRowKeys();
    {
        MultiPointQueryCriterion::RowKey& exist = rowkeys.append();
        exist.mutableGet().append() = PrimaryKeyColumn(
            "pkey",
            PrimaryKeyValue::toStr("some key"));
        exist.mutableUserData() = &userDataForSomeKey;
    }
    {
        MultiPointQueryCriterion::RowKey& exist = rowkeys.append();
        exist.mutableGet().append() = PrimaryKeyColumn(
            "pkey",
            PrimaryKeyValue::toStr("another key"));
        exist.mutableUserData() = &userDataForAnotherKey;
    }
    criterion.mutableTable() = "YourTable";
    criterion.mutableMaxVersions().reset(1);
}
BatchGetRowResponse resp;
Optional<OTSError> res = client.batchGetRow(resp, req);
说明 详细代码可在 batchGetRow@GitHub获取。

批量写(BatchWriteRow)

批量插入、修改或删除一个或多个表中的若干行数据。

BatchWriteRow操作可视为多个PutRow、UpdateRow、DeleteRow操作的集合,各个操作独立执行,独立返回结果,独立计算服务能力单元。

BatchWriteRow可能出现以下两种错误:

  • 请求整体的错误,比如网络超时。这类错误存放在batchWriteRow()返回值中。
  • 单行上的错误,比如主键值不合法。这类错误存放在BatchWriteRowResponse中的每一行上。

示例

static const char kPutRow[] = "PutRow";
static const char kUpdateRow[] = "UpdateRow";
static const char kDeleteRow[] = "DeleteRow";

BatchWriteRowRequest req;
{
    // put row
    BatchWriteRowRequest::Put& put = req.mutablePuts().append();
    put.mutableUserData() = kPutRow;
    put.mutableGet().mutableTable() = kTableName;
    PrimaryKey& pkey = put.mutableGet().mutablePrimaryKey();
    pkey.append() = PrimaryKeyColumn(
        "pkey",
        PrimaryKeyValue::toStr("row to put"));
}
{
    // update row
    BatchWriteRowRequest::Update& update = req.mutableUpdates().append();
    update.mutableUserData() = kUpdateRow;
    update.mutableGet().mutableTable() = kTableName;
    PrimaryKey& pkey = update.mutableGet().mutablePrimaryKey();
    pkey.append() = PrimaryKeyColumn(
        "pkey",
        PrimaryKeyValue::toStr("row to update"));
    RowUpdateChange::Update& attr = update.mutableGet().mutableUpdates().append();
    attr.mutableType() = RowUpdateChange::Update::kPut;
    attr.mutableAttrName() = "attr0";
    attr.mutableAttrValue().reset(AttributeValue::toStr("some value"));
}
{
    // delete row
    BatchWriteRowRequest::Delete& del = req.mutableDeletes().append();
    del.mutableUserData() = kDeleteRow;
    del.mutableGet().mutableTable() = kTableName;
    PrimaryKey& pkey = del.mutableGet().mutablePrimaryKey();
    pkey.append() = PrimaryKeyColumn(
        "pkey",
        PrimaryKeyValue::toStr("row to delete"));
}
BatchWriteRowResponse resp;
Optional<OTSError> res = client.batchWriteRow(resp, req);
说明 详细代码可在 batchWriteRow@GitHub获取。

范围读(GetRange)

读取指定主键范围内的数据。

建议使用RangeIterator。构造RangeIterator需要提供:

  • 异步客户端

  • RangeQueryCriterion与单行读的PointQueryCriterion类似,但RangeQueryCriterion还需要:

    • 设定范围的起始点(包含)和终止点(不包含)。除了正常主键键值之外,还可以使用“负无穷大”(严格小于所有正常主键列值)和“正无穷大”(严格大于所有正常主键列值)两个特殊值。

    • 设定正序读取(由小及大)或者反序读取(由大及小)。默认为正序读取。正序读取时,起始点须小于终止点;反序读取时,起始点须大于终止点。

RangeIterator对象是个Iterator,提供三个接口:

  • moveNext()将RangeIterator对象移动到下一行。刚构造出来的RangeIterator对象必须调用moveNext()才可以取值。如果读取数据失败,moveNext()会将错误显示在返回值中。

  • valid()给出RangeIterator对象是否走到了范围的终点。

  • 如果valid()为true,则可以通过get()读取到行对象。您可以将get()返回的行对象的内容搬移走以避免内存复制。如果移到他处,紧接着的get()将返回搬移后的内容。

示例

RangeQueryCriterion query;
query.mutableTable() = "YourTable";
query.mutableMaxVersions().reset(1);
{
    PrimaryKey& start = query.mutableInclusiveStart();
    start.append() = PrimaryKeyColumn(
        "pkey",
        PrimaryKeyValue::toInfMin());
}
{
    PrimaryKey& end = query.mutableExclusiveEnd();
    end.append() = PrimaryKeyColumn(
        "pkey",
        PrimaryKeyValue::toInfMax());
}
auto_ptr<AsyncClient> aclient(AsyncClient::create(client));
RangeIterator iter(*aclient, query);
for(;;) {
    Optional<OTSError> err = iter.moveNext();
    if (err.present()) {
        // do something with err
        abort();
    }
    if (!iter.valid()) {
        break;
    }
    Row& row = iter.get();
    // do something with row
}
说明 详细代码可在 GetRange@GitHub获取。

指定列读取

表格存储支持无限宽度的行,但一般无需读取整行,只需指定若干列读取即可。 QueryCriterion(PointQueryCriterion、MultiPointQueryCriterion和RangeQueryCriterion的基类)提供了mutableColumnsToGet()方法来指定需要读取的列,既可以是属性列,也可以是主键列,如果为空则读取整行。

如果指定的列在读取的行上不存在,返回的结果里便缺失这个列。表格存储不提供占位符。

在范围读中,如果指定的列全部是属性列,而范围内某行恰好缺少全部指定的列,那么在结果中并不会出现这一行。如果确实需要感知到该行,可以将主键列加入到指定列之中。

指定版本读取

每个属性列可以包含多个版本,每个版本号(时间戳)对应一个列值。读取的时候可以指定读取多少个版本(mutableMaxVersions())以及读取的版本范围(mutableTimeRange())。

最大版本数和版本范围,至少指定其中一项:

  • 如果仅指定版本数,则返回所有版本里从新到旧至多指定数量个数据。
  • 如果仅指定版本范围,则返回该范围内所有数据。
  • 如果同时指定版本数和版本范围,则返回版本范围内从新到旧至多指定数量个数据。

条件写

条件写是指在写一行之前先检查条件,当条件成立才实际写入。表格存储保证条件检查和写入的原子性。

表格存储支持行存在性条件和列值条件:

  • 行存在性条件分为以下几种:

    • Ignore:忽略。默认值,无论行是否存在都写入。
    • ExpectExist:期望存在。行存在则写入。
    • ExpectNotExist:期望不存在。行不存在则写入。
  • 列值条件等同于过滤器