表格存储提供了GetRow接口用于读取单行数据以及BatchGetRow、GetRange等接口用于读取多行数据。
前提条件
- 已初始化Client,详情请参见初始化。
- 已创建数据表并写入数据。
读取单行数据
调用GetRow接口读取一行数据。
读取的结果可能有如下两种:
如果该行存在,则返回该行的各主键列以及属性列。
如果该行不存在,则返回中不包含行,并且不会报错。
接口
/// <summary>
/// 根据给定的主键读取单行数据。
/// </summary>
/// <param name="request">查询数据的请求</param>
/// <returns>GetRow的响应</returns>
public GetRowResponse GetRow(GetRowRequest request);
/// <summary>
/// GetRow的异步形式。
/// </summary>
public Task<GetRowResponse> GetRowAsync(GetRowRequest request);
参数
参数 | 说明 |
tableName | 数据表名称。 |
primaryKey | 行的主键。 说明 设置的主键个数和类型必须和数据表的主键个数和类型一致。 |
columnsToGet | 读取的列集合,列名可以是主键列或属性列。 如果不设置返回的列名,则返回整行数据。 说明
|
maxVersions | 最多读取的版本数。 说明 maxVersions与timeRange必须至少设置一个。
|
timeRange | 读取版本号范围或特定版本号的数据。更多信息,请参见TimeRange。 说明 maxVersions与timeRange必须至少设置一个。
SpecificTime和 时间戳的单位为毫秒,最小值为0,最大值为Int64.MaxValue。 |
filter | 使用过滤器,在服务端对读取结果再进行一次过滤,只返回符合过滤器中条件的数据行。更多信息,请参见过滤器。 说明 当columnsToGet和filter同时使用时,执行顺序是先获取columnsToGet指定的列,再在返回的列中进行条件过滤。 |
示例
示例1
读取一行数据。
//定义行的主键,必须与创建表时的TableMeta中定义的一致。 PrimaryKey primaryKey = new PrimaryKey(); primaryKey.Add("pk0", new ColumnValue(0)); primaryKey.Add("pk1", new ColumnValue("abc")); try { //构造查询请求对象,此处未指定读取的列,默认读取整行数据。 var request = new GetRowRequest(TableName, primaryKey); //调用GetRow接口查询数据。 var response = otsClient.GetRow(request); //输出此行的数据,此处省略,详见示例代码的GitHub链接。 //如果没有抛出异常,则说明执行成功。 Console.WriteLine("Get row succeeded."); } catch (Exception ex) { //如果抛出异常,则说明执行失败,处理异常。 Console.WriteLine("Update table failed, exception:{0}", ex.Message); }
详细代码请参见GetRow@GitHub。
示例2
使用过滤器读取一行数据。
如下示例为查询数据后,只返回col0和col1的数据,同时在col0列和col1列进行过滤,过滤条件是col0等于5或者col1不等于ff。
//定义行的主键,必须与创建表时的TableMeta中定义的一致。 PrimaryKey primaryKey = new PrimaryKey(); primaryKey.Add("pk0", new ColumnValue(0)); primaryKey.Add("pk1", new ColumnValue("abc")); var rowQueryCriteria = new SingleRowQueryCriteria("SampleTable"); rowQueryCriteria.RowPrimaryKey = primaryKey; //条件1为col0列的值等于5。 var filter1 = new RelationalCondition("col0", RelationalCondition.CompareOperator.EQUAL, new ColumnValue(5)); //条件2为col1列的值不等于ff。 var filter2 = new RelationalCondition("col1", RelationalCondition.CompareOperator.NOT_EQUAL, new ColumnValue("ff")); //构造组合条件,包括条件1和条件2,关系是OR。 var filter = new CompositeCondition(CompositeCondition.LogicOperator.OR); filter.AddCondition(filter1); filter.AddCondition(filter2); rowQueryCriteria.Filter = filter; //设置要查询和返回的行,查询和过滤的顺序是先在行的[col0,col1]列上查询,然后再按条件过滤。 rowQueryCriteria.AddColumnsToGet("col0"); rowQueryCriteria.AddColumnsToGet("col1"); //构造GetRowRequest。 var request = new GetRowRequest(rowQueryCriteria); try { //查询。 var response = otsClient.GetRow(request); //输出数据或者相关逻辑操作,此处省略。 //如果没有抛出异常,则说明执行成功。 Console.WriteLine("Get row with filter succeeded."); } catch (Exception ex) { //如果抛出异常,则说明执行失败,处理异常。 Console.WriteLine("Get row with filter failed, exception:{0}", ex.Message); }
详细代码请参见GetRowWithFilter@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操作支持按照确定范围进行正序读取和逆序读取,可以设置要读取的行数。如果范围较大,已扫描的行数或者数据量超过一定限制,会停止扫描,并返回已获取的行和下一个主键信息。您可以根据返回的下一个主键信息,继续发起请求,获取范围内剩余的行。
表格存储表中的行都是按照主键排序的,而主键是由全部主键列按照顺序组成的,所以不能理解为表格存储会按照某列主键排序,这是常见的误区。
注意事项
GetRange操作遵循最左匹配原则,读取数据时,依次比较第一主键列到第四主键列。例如数据表的主键包括PK1、PK2、PK3三个主键列,读取数据时,优先比较PK1是否在开始主键与结束主键的范围内,如果PK1在设置的主键范围内,则不会再比较其他的主键,返回在PK1主键范围内的数据;如果PK1在设置的主键边界上,则继续比较PK2是否在开始主键与结束主键的范围内,以此类推。
GetRange操作可能在如下情况停止执行并返回数据。
扫描的行数据大小之和达到4 MB。
扫描的行数等于5000。
返回的行数等于最大返回行数。
当前剩余的预留读吞吐量已全部使用,余量不足以读取下一条数据。
当使用GetRange扫描的数据量较大时,表格存储每次请求仅会扫描一次(行数大于5000或者大小大于4 MB停止扫描),超过限制的数据不会继续返回,需要通过翻页继续获取后面的数据。
接口
/// <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 | 读取方向。
例如同一表中有两个主键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表示无限大,任何类型的值都比它小。
数据表中的行按主键从小到大排序,读取范围是一个左闭右开的区间,正序读取时,返回的是大于等于起始主键且小于结束主键的所有的行。 |
exclusiveEndPrimaryKey | |
limit | 数据的最大返回行数,此值必须大于 0。 表格存储按照正序或者逆序返回指定的最大返回行数后即结束该操作的执行,即使该区间内仍有未返回的数据。此时可以通过返回的断点记录本次读取到的位置,用于下一次读取。 |
columnsToGet | 读取的列集合,列名可以是主键列或属性列。 如果不设置返回的列名,则返回整行数据。 说明
|
maxVersions | 最多读取的版本数。 说明 maxVersions与timeRange必须至少设置一个。
|
timeRange | 读取版本号范围或特定版本号的数据。更多信息,请参见TimeRange。 说明 maxVersions与timeRange必须至少设置一个。
SpecificTime和[StartTime, EndTime)中只需要设置一个。 时间戳的单位为毫秒,最小值为0,最大值为Int64.MaxValue。 |
filter | 使用过滤器,在服务端对读取结果再进行一次过滤,只返回符合过滤器中条件的数据行。更多信息,请参见过滤器。 说明 当columnsToGet和filter同时使用时,执行顺序是先获取columnsToGet指定的列,再在返回的列中进行条件过滤。 |
nextStartPrimaryKey | 根据返回结果中的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。