读取数据

表格存储提供了GetRow接口用于读取单行数据以及BatchGetRow、GetRange等接口用于读取多行数据。

如果需要了解表格存储各场景的应用案例,请参见快速玩转Tablestore入门与实战

查询方式

表格存储提供的数据读取接口包括GetRow、BatchGetRowGetRange。读取数据时,请根据实际查询场景使用相应查询方式读取数据。

重要

当要读取带有自增主键列的表数据时,请确保已获取到包含自增主键列值在内的完整主键。更多信息,请参见主键列自增。如果未记录自增主键列的值,您可以使用范围读取数据按照第一个主键列确定范围读取数据。

查询方式

说明

适用场景

读取单行数据

调用GetRow接口读取一行数据。

适用于能确定完整主键且要读取行数较少的场景。

批量读取数据

调用BatchGetRow接口一次请求读取多行数据或者一次对多张表进行读取。

BatchGetRow操作由多个GetRow子操作组成,构造子操作的过程与使用GetRow接口时相同。

适用于能确定完整主键,且要读取行数较多或者要读取多个表中数据的场景。

范围读取数据

调用GetRange接口读取一个范围内的数据。

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

适用于能确定完整主键范围或者主键前缀的场景。

重要

如果不能确定主键前缀,您也可以通过设置完整主键范围均为虚拟点INF_MININF_MAX进行全表数据扫描,但是执行此操作会消耗较多计算资源,请谨慎使用。

前提条件

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

读取单行数据

调用GetRow接口读取一行数据。读取的结果可能有如下两种:

  • 如果该行存在,则返回该行的各主键列以及属性列。

  • 如果该行不存在,则返回中不包含行,并且不会报错。

接口

//返回表中的一行数据。
// @param GetRowRequest             执行GetRow操作所需参数的封装。
// @return  GetRowResponse          GetRow操作的响应内容。
GetRow(request *GetRowRequest) (*GetRowResponse, error)                   

参数

参数

说明

TableName

数据表名称。

PrimaryKey

行的主键。主键包括主键列名、主键类型和主键值。

重要

设置的主键个数和类型必须和数据表的主键个数和类型一致。

ColumnsToGet

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

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

  • 如果设置了返回的列名,当某行中指定的列均不存在时,则不返回该行,即返回值为null;当某行中存在部分指定的列时,则返回该行且只返回存在的列。

说明
  • 查询一行数据时,默认返回此行所有列的数据。如果需要只返回特定列,可以通过设置ColumnsToGet参数限制。如果将col0col1加入到ColumnsToGet中,则只返回col0col1列的值。

  • ColumnsToGetFilter同时使用时,执行顺序是先获取ColumnsToGet指定的列,再在返回的列中进行条件过滤。

MaxVersion

最多读取的版本数。

重要

MaxVersionTimeRange必须至少设置一个。

  • 如果仅设置MaxVersion,则最多返回所有版本中从新到旧指定数量版本的数据。

  • 如果仅设置TimeRange,则返回该范围内所有数据或指定版本数据。

  • 如果同时设置MaxVersionTimeRange,则最多返回版本号范围内从新到旧指定数量版本的数据。

TimeRange

读取版本号范围或特定版本号的数据。更多信息,请参见TimeRange

重要

MaxVersionTimeRange必须至少设置一个。

  • 如果仅设置MaxVersion,则最多返回所有版本中从新到旧指定数量版本的数据。

  • 如果仅设置TimeRange,则返回该范围内所有数据或指定版本数据。

  • 如果同时设置MaxVersionTimeRange,则最多返回版本号范围内从新到旧指定数量版本的数据。

  • 如果要查询一个范围的数据,则需要设置StartEnd。StartEnd分别表示起始时间戳和结束时间戳,范围为前闭后开区间,即[Start, End)

  • 如果要查询特定版本号的数据,则需要设置Specific。Specific表示特定的时间戳。

Specific[Start, End)中只需要设置一个。

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

Filter

使用过滤器,在服务端对读取结果再进行一次过滤,只返回符合过滤器中条件的数据行。更多信息,请参见过滤器

说明

ColumnsToGetFilter同时使用时,执行顺序是先获取ColumnsToGet指定的列,再在返回的列中进行条件过滤。

示例

以下示例用于读取一行数据。

getRowRequest := new(tablestore.GetRowRequest)
criteria := new(tablestore.SingleRowQueryCriteria);
putPk := new(tablestore.PrimaryKey)
putPk.AddPrimaryKeyColumn("pk1", "pk1value1")
putPk.AddPrimaryKeyColumn("pk2", int64(2))
putPk.AddPrimaryKeyColumn("pk3", []byte("pk3"))

criteria.PrimaryKey = putPk
getRowRequest.SingleRowQueryCriteria = criteria
getRowRequest.SingleRowQueryCriteria.TableName = tableName 
getRowRequest.SingleRowQueryCriteria.MaxVersion = 1  
getResp, err := client.GetRow(getRowRequest)
if err != nil {
    fmt.Println("getrow failed with error:", err)
} else {
    fmt.Println("get row col0 result is ",getResp.Columns[0].ColumnName, getResp.Columns[0].Value,)
}                   

详细代码请参见GetRow@GitHub

批量读取数据

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

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

注意事项

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

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

  • BatchGetRow操作单次支持读取的最大行数为100行。

参数

更多信息,请参见读取单行数据参数

接口

//返回数据表(Table)中的多行数据。
// @param BatchGetRowRequest             执行BatchGetRow操作所需参数的封装。
// @return  BatchGetRowResponse          BatchGetRow操作的响应内容。
BatchGetRow(request *BatchGetRowRequest) (*BatchGetRowResponse, error)                    

示例

以下示例用于批量一次读取10行数据。

batchGetReq := &tablestore.BatchGetRowRequest{}
mqCriteria := &tablestore.MultiRowQueryCriteria{}

for i := 0; i < 10; i++ {
    pkToGet := new(tablestore.PrimaryKey)
    pkToGet.AddPrimaryKeyColumn("pk1", "pk1value1")
    pkToGet.AddPrimaryKeyColumn("pk2", int64(i))
    pkToGet.AddPrimaryKeyColumn("pk3", []byte("pk3"))
    mqCriteria.AddRow(pkToGet)
    mqCriteria.MaxVersion = 1
}
mqCriteria.TableName = tableName
batchGetReq.MultiRowQueryCriteria = append(batchGetReq.MultiRowQueryCriteria, mqCriteria)
batchGetResponse, err := client.BatchGetRow(batchGetReq)

if err != nil {
    fmt.Println("batchget failed with error:", err)
} else {
    fmt.Println("batchget finished")
}                    

详细代码请参见BatchGetRow@GitHub

范围读取数据

调用GetRange接口读取一个范围内的数据。

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

说明

表格存储表中的行都是按照主键排序的,而主键是由全部主键列按照顺序组成的,所以不能理解为表格存储会按照某列主键排序,这是常见的误区。

注意事项

GetRange操作遵循最左匹配原则,读取数据时,依次比较第一主键列到第四主键列。例如表的主键包括PK1、PK2、PK3三个主键列,读取数据时,优先比较PK1是否在开始主键与结束主键的范围内,如果PK1在设置的主键范围内,则不会再比较其他的主键,返回在PK1主键范围内的数据;如果PK1在设置的主键边界上,则继续比较PK2是否在开始主键与结束主键的范围内,以此类推。关于范围查询原理的更多信息,请参见GetRange范围查询详解

GetRange操作可能在如下情况停止执行并返回数据。

  • 扫描的行数据大小之和达到4 MB。

  • 扫描的行数等于5000。

  • 返回的行数等于最大返回行数。

  • 当前剩余的预留读吞吐量已全部使用,余量不足以读取下一条数据。

当使用GetRange扫描的数据量较大时,表格存储每次请求仅会扫描一次(行数大于5000或者大小大于4 MB停止扫描),超过限制的数据不会继续返回,需要通过翻页继续获取后面的数据。

接口

//从表中查询一个范围内的多行数据。
// @param GetRangeRequest           执行GetRange操作所需参数的封装。
// @return GetRangeResponse         GetRange操作的响应内容。
GetRange(request *GetRangeRequest) (*GetRangeResponse,error)                   

参数

参数

说明

TableName

数据表名称。

Direction

读取方向。

  • 如果值为正序(FORWARD),则起始主键必须小于结束主键,返回的行按照主键由小到大的顺序进行排列。

  • 如果值为逆序(BACKWARD),则起始主键必须大于结束主键,返回的行按照主键由大到小的顺序进行排列。

假设同一表中有两个主键AB,A小于B,如果正序读取[A, B),则按从AB的顺序返回主键大于等于A且小于B的行数据;如果逆序读取[B, A),则按从BA的顺序返回大于A且小于等于B的行数据。

StartPrimaryKey

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

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

  • StartPrimaryKey表示起始主键,如果该行存在,则返回结果中一定会包含此行。

  • EndPrimaryKey表示结束主键,无论该行是否存在,返回结果中都不会包含此行。

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

EndPrimaryKey

Limit

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

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

ColumnsToGet

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

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

  • 如果设置了返回的列名,当某行中指定的列均不存在时,则不返回该行,即返回值为null;当某行中存在部分指定的列时,则返回该行且只返回存在的列。

说明
  • 查询一行数据时,默认返回此行所有列的数据。如果需要只返回特定列,可以通过设置ColumnsToGet参数限制。如果将col0col1加入到ColumnsToGet中,则只返回col0col1列的值。

  • 如果某行数据的主键属于读取范围,但是该行数据不包含指定返回的列,那么返回结果中不包含该行数据。

  • ColumnsToGetFilter同时使用时,执行顺序是先获取ColumnsToGet指定的列,再在返回的列中进行条件过滤。

MaxVersions

最多读取的版本数。

重要

MaxVersionTimeRange必须至少设置一个。

  • 如果仅设置MaxVersion,则最多返回所有版本中从新到旧指定数量版本的数据。

  • 如果仅设置TimeRange,则返回该范围内所有数据或指定版本数据。

  • 如果同时设置MaxVersionTimeRange,则最多返回版本号范围内从新到旧指定数量版本的数据。

TimeRange

读取版本号范围或特定版本号的数据。更多信息,请参见TimeRange

重要

MaxVersionTimeRange必须至少设置一个。

  • 如果仅设置MaxVersion,则最多返回所有版本中从新到旧指定数量版本的数据。

  • 如果仅设置TimeRange,则返回该范围内所有数据或指定版本数据。

  • 如果同时设置MaxVersionTimeRange,则最多返回版本号范围内从新到旧指定数量版本的数据。

  • 如果要查询一个范围的数据,则需要设置StartEnd。StartEnd分别表示起始时间戳和结束时间戳,范围为前闭后开区间,即[Start, End)

  • 如果要查询特定版本号的数据,则需要设置Specific。Specific表示特定的时间戳。

Specific[Start, End)中只需要设置一个。

时间戳的单位为毫秒,最小值为0,最大值为INT64.MAX

Filter

使用过滤器,在服务端对读取结果再进行一次过滤,只返回符合过滤器中条件的数据行。更多信息,请参见过滤器

说明

ColumnsToGetFilter同时使用时,执行顺序是先获取ColumnsToGet指定的列,再在返回的列中进行条件过滤。

NextStartPrimaryKey

根据返回结果中的NextStartPrimaryKey判断数据是否全部读取。

  • 当返回结果中NextStartPrimaryKey不为空时,可以使用此返回值作为下一次GetRange操作的起始点继续读取数据。

  • 当返回结果中NextStartPrimaryKey为空时,表示读取范围内的数据全部返回。

示例

以下示例用于按照范围读取数据。

getRangeRequest := &tablestore.GetRangeRequest{}
rangeRowQueryCriteria := &tablestore.RangeRowQueryCriteria{}
rangeRowQueryCriteria.TableName = tableName

startPK := new(tablestore.PrimaryKey)
startPK.AddPrimaryKeyColumnWithMinValue("pk1")
startPK.AddPrimaryKeyColumnWithMinValue("pk2")
startPK.AddPrimaryKeyColumnWithMinValue("pk3")
endPK := new(tablestore.PrimaryKey)
endPK.AddPrimaryKeyColumnWithMaxValue("pk1")
endPK.AddPrimaryKeyColumnWithMaxValue("pk2")
endPK.AddPrimaryKeyColumnWithMaxValue("pk3")
rangeRowQueryCriteria.StartPrimaryKey = startPK
rangeRowQueryCriteria.EndPrimaryKey = endPK
rangeRowQueryCriteria.Direction = tablestore.FORWARD
rangeRowQueryCriteria.MaxVersion = 1
rangeRowQueryCriteria.Limit = 10
getRangeRequest.RangeRowQueryCriteria = rangeRowQueryCriteria

getRangeResp, err := client.GetRange(getRangeRequest)

fmt.Println("get range result is " ,getRangeResp)

for {
    if err != nil {
        fmt.Println("get range failed with error:", err)
    }
    for _, row := range getRangeResp.Rows {
        fmt.Println("range get row with key", row.PrimaryKey.PrimaryKeys[0].Value, row.PrimaryKey.PrimaryKeys[1].Value, row.PrimaryKey.PrimaryKeys[2].Value)
    }
    if getRangeResp.NextStartPrimaryKey == nil {
        break
    } else {
        fmt.Println("next pk is :", getRangeResp.NextStartPrimaryKey.PrimaryKeys[0].Value, getRangeResp.NextStartPrimaryKey.PrimaryKeys[1].Value, getRangeResp.NextStartPrimaryKey.PrimaryKeys[2].Value)
        getRangeRequest.RangeRowQueryCriteria.StartPrimaryKey = getRangeResp.NextStartPrimaryKey
        getRangeResp, err = client.GetRange(getRangeRequest)
    }
    fmt.Println("continue to query rows")
}
fmt.Println("range get row finished")

详细代码请参见GetRange@GitHub