Tablestore provides operations to read data from tables: read a single row, read multiple rows in a batch, scan a primary key range, or iterate over a range using an iterator.
For more information, see Quick start guide to Tablestore with real-world case studies.
Query methods
Tablestore provides three operations for reading data: GetRow, BatchGetRow, and GetRange. Choose the appropriate operation based on your query scenario.
To read from a table with an auto-increment primary key column, you must first retrieve all primary key column values, including the auto-increment value. For more information, see Auto-increment primary key column. If the auto-increment value is unavailable, use GetRange to scan based on the first primary key column.
|
Operation |
Description |
When to use |
|
Reads a single row by its primary key using the GetRow operation. |
All primary key columns are known and you need to read a small number of rows. |
|
|
Reads multiple rows from one or more tables in a single call using the BatchGetRow operation. Each row is read independently and returns its own result. |
All primary key columns are known and you need to read a large number of rows, or read from multiple tables. |
|
|
Read data whose primary key values are within a specific range |
Scans rows whose primary key values fall within a specified range using the GetRange operation. Supports forward and backward scanning, row limits, and automatic pagination via |
The range of primary key values or a primary key prefix can be determined. Important
If no prefix is known, set the start key to INF_MIN and the end key to INF_MAX to scan the entire table. This consumes significant compute resources—proceed with caution. |
|
Read data whose primary key values are within a specific range by using an iterator |
Reads rows in a primary key range using an iterator, which handles pagination automatically. |
The primary key range or prefix can be determined, and you want to iterate over results without managing pagination manually. |
Prerequisites
Before you begin, ensure that you have:
An OTSClient instance initialized. For more information, see Initialize an OTSClient instance.
A data table created with data written to it. For more information, see Create data tables and Write data.
Read a single row of data
Call the GetRow operation to read a single row by its primary key.
API operation
/// <summary>
/// Read a single row based on the specified primary key.
/// </summary>
/// <param name="request">Data query request</param>
/// <returns>Response of GetRow</returns>
public GetRowResponse GetRow(GetRowRequest request);
/// <summary>
/// Asynchronous version of GetRow.
/// </summary>
public Task<GetRowResponse> GetRowAsync(GetRowRequest request);
Parameters
|
Parameter |
Description |
|
tableName |
The name of the table. |
|
primaryKey |
The primary key of the row to read, specified as column name, type, and value. Important
The number and types of primary key columns must match the table schema exactly. |
|
columnsToGet |
The columns to return—primary key columns or attribute columns. If omitted, all columns are returned.
Note
|
|
maxVersions |
The maximum number of data versions to return. Important
Specify at least one of
|
|
timeRange |
The version time range or specific version to read. For more information, see TimeRange. Important
Specify at least one of
Only one of Valid range: 0 to |
|
filter |
A server-side filter applied after data retrieval. Only rows matching the filter conditions are returned. For more information, see Use a filter. Note
If both |
Sample code
Read a row of data
The following sample code provides an example on how to read a row of data:
// Specify the primary key. The columns and types must match the table schema.
PrimaryKey primaryKey = new PrimaryKey();
primaryKey.Add("pk0", new ColumnValue(0));
primaryKey.Add("pk1", new ColumnValue("abc"));
try
{
// Build the request. Omitting columnsToGet returns the entire row.
var request = new GetRowRequest(TableName, primaryKey);
// Call GetRow.
var response = otsClient.GetRow(request);
// Process the returned row data.
// (Omitted here—see the GitHub sample for the full implementation.)
Console.WriteLine("Get row succeeded.");
}
catch (Exception ex)
{
Console.WriteLine("Update table failed, exception:{0}", ex.Message);
}
To view the detailed sample code, visit GetRow@GitHub.
Read a row of data by using a filter
The following example reads col0 and col1 and returns the row only if the value of col0 is 5 or the value of col1 is not ff.
// Specify the primary key. The columns and types must match the table schema.
PrimaryKey primaryKey = new PrimaryKey();
primaryKey.Add("pk0", new ColumnValue(0));
primaryKey.Add("pk1", new ColumnValue("abc"));
var rowQueryCriteria = new SingleRowQueryCriteria("SampleTable");
rowQueryCriteria.RowPrimaryKey = primaryKey;
// Condition 1: col0 == 5
var filter1 = new RelationalCondition("col0",
RelationalCondition.CompareOperator.EQUAL,
new ColumnValue(5));
// Condition 2: col1 != "ff"
var filter2 = new RelationalCondition("col1", RelationalCondition.CompareOperator.NOT_EQUAL, new ColumnValue("ff"));
// Combine with OR: return the row if either condition is met.
var filter = new CompositeCondition(CompositeCondition.LogicOperator.OR);
filter.AddCondition(filter1);
filter.AddCondition(filter2);
rowQueryCriteria.Filter = filter;
// Fetch only col0 and col1, then apply the filter.
rowQueryCriteria.AddColumnsToGet("col0");
rowQueryCriteria.AddColumnsToGet("col1");
var request = new GetRowRequest(rowQueryCriteria);
try
{
var response = otsClient.GetRow(request);
// Process the returned row data.
// (Omitted here—see the GitHub sample for the full implementation.)
Console.WriteLine("Get row with filter succeeded.");
}
catch (Exception ex)
{
Console.WriteLine("Get row with filter failed, exception:{0}", ex.Message);
}
To view the detailed sample code, visit GetRowWithFilter@GitHub.
Read multiple rows of data at a time
Call the BatchGetRow operation to read multiple rows from one or more tables in a single request. Each row is processed as an independent GetRow call—Tablestore returns a separate result for each row.
Usage notes
Some rows in a batch request may fail individually. Errors for those rows appear in the BatchGetRowResponse rather than as thrown exceptions. Always inspect the response to confirm each row was read successfully.
The same parameters apply to all rows in the request. For example, setting
ColumnsToGet=[colA]reads onlycolAfrom every row.A single BatchGetRow request can read a maximum of 100 rows.
API operation
/// <summary>
/// Read multiple rows from one or more tables in a single call.
/// Each row is read and billed independently, but batching reduces
/// round-trip overhead compared to multiple GetRow calls.
/// </summary>
/// <param name="request">Request instance</param>
/// <returns>Response instance</returns>
public BatchGetRowResponse BatchGetRow(BatchGetRowRequest request);
/// <summary>
/// Asynchronous version of BatchGetRow.
/// </summary>
public Task<BatchGetRowResponse> BatchGetRowAsync(BatchGetRowRequest request);
Sample code
The following example reads 10 rows in a single BatchGetRow call:
// Build primary keys for 10 rows.
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);
var response = otsClient.BatchGetRow(request);
var tableRows = response.RowDataGroupByTable;
var rows = tableRows[TableName];
// Inspect each row's result individually—some rows may have failed.
// (Omitted here—see the GitHub sample for the full implementation.)
}
catch (Exception ex)
{
Console.WriteLine("Batch get row failed, exception:{0}", ex.Message);
}
To view the detailed sample code, visit BatchGetRow@GitHub.
Read data whose primary key values are within a specific range
Call the GetRange operation to scan rows whose primary key values fall within a specified range. The scan can go forward or backward, and you can cap the number of rows returned. If the scan hits a limit (data volume, row count, or reserved throughput), it stops early and returns a nextStartPrimaryKey value. Use that value as the start key in a follow-up request to read the remaining rows.
All rows in a Tablestore table are sorted by their full composite primary key, not by any individual primary key column.
Usage notes
GetRange uses the leftmost matching principle: Tablestore compares primary key column values from left to right. When a row's value for the first primary key column (PK1) falls within the specified range, the row is returned without evaluating further columns. When PK1 is out of range, Tablestore continues evaluating the remaining columns in the same way.For more information about range query principles, see GetRange range query details.
A GetRange operation stops early when any of the following limits is reached:
The scanned data reaches 4 MB.
The number of scanned rows reaches 5,000.
The number of returned rows reaches the specified
limit.Reserved read throughput is exhausted before the next row can be read.
API operation
/// <summary>
/// Read rows whose primary key values are within the specified range.
/// </summary>
/// <param name="request">Request instance</param>
/// <returns>Response instance</returns>
public GetRangeResponse GetRange(GetRangeRequest request);
/// <summary>
/// Asynchronous version of GetRange.
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public Task<GetRangeResponse> GetRangeAsync(GetRangeRequest request);
Parameters
|
Parameter |
Description |
|
tableName |
The name of the table. |
|
direction |
The scan direction.
For example, given primary key values A and B where A < B: setting direction to FORWARD with range |
|
inclusiveStartPrimaryKey |
The start and end primary keys of the range. Both must be valid primary key columns, or virtual columns of type INF_MIN or INF_MAX. The number of columns must match the table's primary key schema. INF_MIN is smaller than all other values. INF_MAX is larger than all other values.
The range is a left-closed, right-open interval. In the forward direction, rows with keys ≥ start and < end are returned. |
|
exclusiveEndPrimaryKey |
|
|
limit |
The maximum number of rows to return. Must be greater than 0. When the limit is reached, the scan stops and returns |
|
columnsToGet |
The columns to return—primary key columns or attribute columns. If omitted, all columns are returned.
Note
|
|
maxVersions |
The maximum number of data versions to return. Important
Specify at least one of
|
|
timeRange |
The version time range or specific version to read. For more information, see TimeRange. Important
Specify at least one of
Only one of Valid range: 0 to |
|
filter |
A server-side filter applied after data retrieval. Only rows matching the filter conditions are returned. For more information, see Configure filter. Note
If both |
|
nextStartPrimaryKey |
The start key for the next read request, returned when the response is paginated.
|
Sample code
The following example scans all rows with primary key values between (0, INF_MIN) and (100, INF_MAX), handling pagination automatically:
// Define the key range: pk0 from 0 (inclusive) to 100 (exclusive).
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);
// Collect all rows, paginating until nextStartPrimaryKey is null.
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);
}
}
// Process all collected rows.
// (Omitted here—see the GitHub sample for the full implementation.)
Console.WriteLine("Get range succeeded");
}
catch (Exception ex)
{
Console.WriteLine("Get range failed, exception:{0}", ex.Message);
}
To view the detailed sample code, visit GetRange@GitHub.
Read data whose primary key values are within a specific range by using an iterator
Call the GetRangeIterator operation to scan a primary key range using an iterator. Unlike GetRange, the iterator handles pagination automatically—no need to check nextStartPrimaryKey and issue follow-up requests manually.
API operation
/// <summary>
/// Scan rows whose primary key values are within the specified range.
/// Returns an iterator that yields one row at a time, handling pagination internally.
/// </summary>
/// <param name="request"><see cref="GetIteratorRequest"/></param>
/// <returns>An iterator of <see cref="RowDataFromGetRange"/>.</returns>
public IEnumerable<RowDataFromGetRange> GetRangeIterator(GetIteratorRequest request);
Sample code
The following example reads all rows with primary key values between (0, "a") and (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"));
// Track capacity units consumed during iteration.
var cu = new CapacityUnit(0, 0);
try
{
// Filters are supported on GetIteratorRequest.
var request = new GetIteratorRequest(TableName, GetRangeDirection.Forward, inclusiveStartPrimaryKey,
exclusiveEndPrimaryKey, cu);
var iterator = otsClient.GetRangeIterator(request);
foreach (var row in iterator)
{
// Process each row.
}
Console.WriteLine("Iterate row succeeded");
}
catch (Exception ex)
{
Console.WriteLine("Iterate row failed, exception:{0}", ex.Message);
}
To view the detailed sample code, visit GetRangeIterator@GitHub.