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

如需了解表格存储各场景的应用案例,请参见适用场景

前提条件

  • 已初始化Client,详情请参见初始化
  • 已创建数据表并写入数据。

批量写(BatchWriteRow)

批量写接口用于在一次请求中进行批量的写入操作,也支持一次对多个数据表进行写入。BatchWriteRow操作由多个PutRow、UpdateRow、DeleteRow子操作组成,构造子操作的过程与使用PutRow接口、UpdateRow接口和DeleteRow接口时相同,也支持使用条件更新。

BatchWriteRow的各个子操作独立执行,表格存储会分别返回各个子操作的执行结果。

由于批量写入可能存在部分行失败的情况,失败行的Index及错误信息在返回的BatchWriteRowResponse中,但并不抛出异常。因此调用BatchWriteRow接口时,需要检查返回值,判断每行的状态是否成功;如果不检查返回值,则可能会忽略掉部分操作的失败。

当服务端检查到某些操作出现参数错误时,BatchWriteRow接口可能会抛出参数错误的异常,此时该请求中所有的操作都未执行。

  • 接口
    /// <summary>
    /// <para>批量插入,修改或删除一个或多个表中的若干行数据。</para>
    /// <para>BatchWriteRow操作可视为多个PutRow、UpdateRow、DeleteRow操作的集合,各个操作独立执行,独立返回结果,独立计算服务能力单元。</para>
    /// <para>与执行大量的单行写操作相比,使用BatchWriteRow操作可以有效减少请求的响应时间,提高数据的写入速率。</para>
    /// </summary>
    /// <param name="request">请求实例</param>
    /// <returns>响应实例</returns>
    public BatchWriteRowResponse BatchWriteRow(BatchWriteRowRequest request);
    
    /// <summary>
    /// BatchWriteRow的异步形式。
    /// </summary>
    /// <param name="request"></param>
    /// <returns></returns>
    public Task<BatchWriteRowResponse> BatchWriteRowAsync(BatchWriteRowRequest request);            
  • 参数

    详细参数说明请参见单行数据操作

  • 示例

    批量写入100行数据。

    //构造批量写的请求对象,设置100行数据的主键。
    var request = new BatchWriteRowRequest();
    var rowChanges = new RowChanges();
    for (int i = 0; i < 100; i++)
    {
        PrimaryKey primaryKey = new PrimaryKey();
        primaryKey.Add("pk0", new ColumnValue(i));
        primaryKey.Add("pk1", new ColumnValue("abc"));
    
        //定义要写入该行的属性列。
        UpdateOfAttribute attribute = new UpdateOfAttribute();
        attribute.AddAttributeColumnToPut("col0", new ColumnValue(0));
        attribute.AddAttributeColumnToPut("col1", new ColumnValue("a"));
        attribute.AddAttributeColumnToPut("col2", new ColumnValue(true));
    
        rowChanges.AddUpdate(new Condition(RowExistenceExpectation.IGNORE), primaryKey, attribute);
    }
    
    request.Add(TableName, rowChanges);
    
    try
    {
        //调用BatchWriteRow接口写入数据。
        var response = otsClient.BatchWriteRow(request);
        var tableRows = response.TableRespones;
        var rows = tableRows[TableName];
    
        //批量操作可能部分成功部分失败,需要检查每行的状态是否成功,详见示例代码的GitHub链接。
    }
    catch (Exception ex)
    {
        //如果抛出异常,则说明执行失败,处理异常。
        Console.WriteLine("Batch put row failed, exception:{0}", ex.Message);
    }           

    详细代码请参见BatchWriteRow@GitHub

批量读(BatchGetRow)

批量读接口用于一次请求读取多行数据,也支持一次对多张表进行读取。BatchGetRow由多个GetRow子操作组成。构造子操作的过程与使用GetRow接口时相同,也支持使用过滤器。

批量读取的所有行采用相同的参数条件,例如ColumnsToGet=[colA],则要读取的所有行都只读取colA列。

BatchGetRow的各个子操作独立执行,表格存储会分别返回各个子操作的执行结果。

由于批量读取可能存在部分行失败的情况,失败行的错误信息在返回的BatchGetRowResponse中,但并不抛出异常。因此调用BatchGetRow接口时,需要检查返回值,判断每行的状态是否成功。

  • 接口
    /// <summary>
    /// <para>批量读取一个或多个表中的若干行数据。</para>
    /// <para>BatchGetRow操作可视为多个GetRow操作的集合,各个操作独立执行,独立返回结果,独立计算服务能力单元。</para>
    /// 与执行大量的GetRow操作相比,使用BatchGetRow操作可以有效减少请求的响应时间,提高数据的读取速率。
    /// </summary>
    /// <param name="request">请求实例</param>
    /// <returns>响应实例</returns>
    public BatchGetRowResponse BatchGetRow(BatchGetRowRequest request);
    
    /// <summary>
    /// BatchGetRow的异步形式。
    /// </summary>
    public Task<BatchGetRowResponse> BatchGetRowAsync(BatchGetRowRequest request);            
  • 参数

    详细参数说明请参见单行数据操作

  • 示例

    批量一次读取10行。

    //构造批量读的请求对象,设置10行数据的主键。
    List<PrimaryKey> primaryKeys = new List<PrimaryKey>();
    for (int i = 0; i < 10; i++)
    {
        PrimaryKey primaryKey = new PrimaryKey();
        primaryKey.Add("pk0", new ColumnValue(i));
        primaryKey.Add("pk1", new ColumnValue("abc"));
        primaryKeys.Add(primaryKey);
    }
    
    try
    {
        BatchGetRowRequest request = new BatchGetRowRequest();
        request.Add(TableName, primaryKeys);
    
        //调用BatchGetRow接口查询10行数据。
        var response = otsClient.BatchGetRow(request);
        var tableRows = response.RowDataGroupByTable;
        var rows = tableRows[TableName];
    
        //输出rows中的数据,此处省略,详见示例代码的GitHub链接。
    
        //批量操作可能部分成功部分失败,需要检查每行的状态是否成功,详见示例代码的GitHub链接。
    }
    catch (Exception ex)
    {
        //如果抛出异常,则说明执行失败,处理异常。
        Console.WriteLine("Batch get row failed, exception:{0}", ex.Message);
    }            

    详细代码请参见BatchGetRow@GitHub

范围读(GetRange)

范围读接口用于读取一个主键范围内的数据。

范围读接口支持按照确定范围进行正序读取和逆序读取,可以设置要读取的行数。如果范围较大,已扫描的行数或者数据量超过一定限制,会停止扫描,并返回已获取的行和下一个主键信息。您可以根据返回的下一个主键信息,继续发起请求,获取范围内剩余的行。

GetRange操作可能在如下情况停止执行并返回数据。
  • 扫描的行数据大小之和达到4 MB。
  • 扫描的行数等于5000。
  • 返回的行数等于最大返回行数。
  • 当前剩余的预留读吞吐量已全部使用,余量不足以读取下一条数据。
说明 表格存储表中的行默认是按照主键排序的,而主键是由全部主键列按照顺序组成的,所以不能理解为表格存储会按照某列主键排序,这是常见的误区。
  • 接口
    /// <summary>
    /// 根据范围条件获取多行数据。
    /// </summary>
    /// <param name="request">请求实例</param>
    /// <returns>响应实例</returns>
    public GetRangeResponse GetRange(GetRangeRequest request);
    
    /// <summary>
    /// GetRange的异步版本。
    /// </summary>
    /// <param name="request"></param>
    /// <returns></returns>
    public Task<GetRangeResponse> GetRangeAsync(GetRangeRequest request);              
  • 参数
    参数 说明
    tableName 数据表名称。
    direction 读取方向。
    • 如果值为正序(FORWARD),则起始主键必须小于结束主键,返回的行按照主键由小到大的顺序进行排列。
    • 如果值为逆序(BACKWARD),则起始主键必须大于结束主键,返回的行按照主键由大到小的顺序进行排列。

    例如同一表中有两个主键A和B,A<B。如正序读取[A, B),则按从A至B的顺序返回主键大于等于A、小于B的行;逆序读取[B, A),则按从B至A的顺序返回大于A、小于等于B的数据。

    inclusiveStartPrimaryKey 本次范围读的起始主键和结束主键,起始主键和结束主键需要是有效的主键或者是由INF_MIN和INF_MAX类型组成的虚拟点,虚拟点的列数必须与主键相同。

    其中INF_MIN表示无限小,任何类型的值都比它大;INF_MAX表示无限大,任何类型的值都比它小。

    • inclusiveStartPrimaryKey表示起始主键,如果该行存在,则返回结果中一定会包含此行。
    • exclusiveEndPrimaryKey表示结束主键,无论该行是否存在,返回结果中都不会包含此行。

    数据表中的行按主键从小到大排序,读取范围是一个左闭右开的区间,正序读取时,返回的是大于等于起始主键且小于结束主键的所有的行。

    exclusiveEndPrimaryKey
    limit 数据的最大返回行数,此值必须大于 0。

    表格存储按照正序或者逆序返回指定的最大返回行数后即结束该操作的执行,即使该区间内仍有未返回的数据。此时可以通过返回的断点记录本次读取到的位置,用于下一次读取。

    columnsToGet 读取的列集合,列名可以是主键列或属性列。

    如果不设置返回的列名,则返回整行数据。

    说明
    • 查询一行数据时,默认返回此行所有列的数据。如果需要只返回特定列,可以通过设置columnsToGet参数限制。如果将col0和col1加入到columnsToGet中,则只返回col0和col1列的值。
    • 如果某行数据的主键属于读取范围,但是该行数据不包含指定返回的列,那么返回结果中不包含该行数据。
    • 当columnsToGet和filter同时使用时,执行顺序是先获取columnsToGet指定的列,再在返回的列中进行条件过滤。
    maxVersions 最多读取的版本数。
    说明 maxVersions与timeRange必须至少设置一个。
    • 如果仅设置maxVersions,则返回所有版本中从新到旧最多指定数量版本的数据。
    • 如果仅设置timeRange,则返回该范围内所有数据或指定版本数据。
    • 如果同时设置maxVersions和timeRange,则返回版本号范围内从新到旧最多指定数量版本的数据。
    timeRange 读取版本号范围或特定版本号的数据。详情请参见TimeRange
    说明 maxVersions与timeRange必须至少设置一个。
    • 如果仅设置maxVersions,则返回所有版本中从新到旧最多指定数量版本的数据。
    • 如果仅设置timeRange,则返回该范围内所有数据或指定版本数据。
    • 如果同时设置maxVersions和timeRange,则返回版本号范围内从新到旧最多指定数量版本的数据。
    • 如果查询一个范围的数据,则需要设置StartTime和EndTime。StartTime和EndTime分别表示起始时间戳和结束时间戳,范围为前闭后开区间,即[StartTime, EndTime)。
    • 如果查询特定版本号的数据,则需要设置SpecificTime。SpecificTime表示特定的时间戳。

    SpecificTime和[StartTime, EndTime)中只需要设置一个。

    时间戳的单位为毫秒,最小值为0,最大值为Int64.MaxValue。

    filter 使用过滤器,在服务端对读取结果再进行一次过滤,只返回符合过滤器中条件的数据行,详情请参见过滤器
    说明 当columnsToGet和filter同时使用时,执行顺序是先获取columnsToGet指定的列,再在返回的列中进行条件过滤。
    nextStartPrimaryKey 根据返回结果中的nextStartPrimaryKey判断数据是否全部读取。
    • 当返回结果中nextStartPrimaryKey不为空时,可以使用此返回值作为下一次GetRange操作的起始点继续读取数据。
    • 当返回结果中nextStartPrimaryKey为空时,表示读取范围内的数据全部返回。
  • 示例

    按照范围读取数据。

    //读取(0, INF_MIN)到(100, INF_MAX)范围内的所有行。
    var inclusiveStartPrimaryKey = new PrimaryKey();
    inclusiveStartPrimaryKey.Add("pk0", new ColumnValue(0));
    inclusiveStartPrimaryKey.Add("pk1", ColumnValue.INF_MIN);
    
    var exclusiveEndPrimaryKey = new PrimaryKey();
    exclusiveEndPrimaryKey.Add("pk0", new ColumnValue(100));
    exclusiveEndPrimaryKey.Add("pk1", ColumnValue.INF_MAX);
    
    try
    {
        //构造范围读的请求对象。
        var request = new GetRangeRequest(TableName, GetRangeDirection.Forward,
                        inclusiveStartPrimaryKey, exclusiveEndPrimaryKey);
    
        var response = otsClient.GetRange(request);
    
        //如果一次没有返回所有数据,则需要继续查询。
        var rows = response.RowDataList;
        var nextStartPrimaryKey = response.NextPrimaryKey;
        while (nextStartPrimaryKey != null)
        {
            request = new GetRangeRequest(TableName, GetRangeDirection.Forward,
                            nextStartPrimaryKey, exclusiveEndPrimaryKey);
            response = otsClient.GetRange(request);
            nextStartPrimaryKey = response.NextPrimaryKey;
            foreach (RowDataFromGetRange row in response.RowDataList)
            {
                rows.Add(row);
            }
        }
    
        //输出rows中的数据,此处省略,详见示例代码的GitHub链接。
    
        //如果没有抛出异常,则说明执行成功。
        Console.WriteLine("Get range succeeded");
    }
    catch (Exception ex)
    {
        //如果抛出异常,则说明执行失败,处理异常。
        Console.WriteLine("Get range failed, exception:{0}", ex.Message);
    }            

    详细代码请参见GetRange@GitHub

迭代读(GetRangeIterator)

迭代读取数据。

  • 接口
    /// <summary>
    /// 根据范围条件获取多行数据,返回用来迭代每一行数据的迭代器。
    /// </summary>
    /// <param name="request"><see cref="GetIteratorRequest"/></param>
    /// <returns>返回<see cref="RowDataFromGetRange"/>的迭代器。</returns>
    public IEnumerable<RowDataFromGetRange> GetRangeIterator(GetIteratorRequest request);           
  • 示例

    迭代读取(0, "a")到(1000, "xyz")范围内的所有行。

    //读取(0, "a")到(1000, "xyz")范围内的所有行。
    PrimaryKey inclusiveStartPrimaryKey = new PrimaryKey();
    inclusiveStartPrimaryKey.Add("pk0", new ColumnValue(0));
    inclusiveStartPrimaryKey.Add("pk1", new ColumnValue("a"));
    
    PrimaryKey exclusiveEndPrimaryKey = new PrimaryKey();
    exclusiveEndPrimaryKey.Add("pk0", new ColumnValue(1000));
    exclusiveEndPrimaryKey.Add("pk1", new ColumnValue("xyz"));
    
    //构造一个CapacityUnit,用于记录迭代过程中消耗的CU值。
    var cu = new CapacityUnit(0, 0);
    
    try
    {
        //构造一个GetIteratorRequest,也支持使用过滤条件。
        var request = new GetIteratorRequest(TableName, GetRangeDirection.Forward, inclusiveStartPrimaryKey,
                                                    exclusiveEndPrimaryKey, cu);
    
        var iterator = otsClient.GetRangeIterator(request);
        //遍历迭代器,读取数据。
        foreach (var row in iterator)
        {
            //处理逻辑。
        }
    
        Console.WriteLine("Iterate row succeeded");
    } 
    catch (Exception ex)
    {
        Console.WriteLine("Iterate row failed, exception:{0}", ex.Message);
    }            

    详细代码请参见GetRangeIterator@GitHub