1.5.8 扫描记录

优质
小牛编辑
138浏览
2023-12-01

ScanResult scan(ScanRequest request)

功能

扫描操作,每个扫描过的记录消耗1个读配额(即使不满足过滤条件),每个Lazy二级索引需要1个额外读配额

方法参数

request : ScanRequest : required

ScanRequest包括以下部分

1.tableName : String : required

指定扫描的表名

2.indexName :String : optional

指定扫描的二级索引名,如果不指定,即扫描主记录

3.startKey : Map< String, Datum > :optional

查询范围开始,包含startKey,如果startKey不是完整键,而是部分key的前缀,则实际查询的startKey为{startKey, 最小可能的后缀}补全形式

4.stopKey : Map< String, Datum > :optional

查询范围结束,不包含stopKey,如果stopKey不是完整键,而是部分key的前缀,则实际查询的stopKey为{stopKey, 最大可能的后缀}补全形式

5.attributes : List< String > :optional

需要返回的属性列表,不指定表示返回所有属性

6.condition : String : optional

类SQL WHERE语句的查询条件。 注意:与SQL不同,此条件仅作为过滤条件,不影响具体查询计划(index, startKey, endKey),进行范围查询时需要显示设置index和startKey以及endKey。每个扫描的记录均计入读配额,即使不满足查询条件。尽量避免使用条件过滤,尤其是当过滤掉的记录占一半以上时,强烈不建议使用。

7.limit :int : optinal

返回记录的最大数目,返回数目可能小于此值(如超出表的读配额时), 默认为10, 范围(0, 1000]

8.reverse : boolean : optional

是否进行逆序扫描,进行逆序扫描时startKey应大于endKey

注意:逆序查询效率较低,谨慎使用,建议设置对应的Key为逆序存储

9.inGlobalOrder :boolean :optional

是否全局有序扫描,对于设置了实体组键且开启了哈希的表,需要设置该值为true才能保证结果有序

10.action :ScanAction : optional

scan时的连带操作,包括COUNT,DELETE和UPDATE, 类似SQL的select count(*) / update XXX / delete XXX from table where XXX 语义

方法返回值

scanResult : ScanResult

scanResult包括以下内容

1.records : List< Map< String,Datum > >

扫描到的记录

2.nextStartKey : Map< String,Datum >

下一个需要扫描的记录主键,NULL表示达到制定的结束位置

异常错误码

INTERNAL_ERROR(1) : 服务器异常

ACCESS_DENIED(4) : 用户对该表没有读权限

VALIDATION_FAILED(5): 参数设置错误

THROUGHPUT_EXCEED(8): 当前读写速度已超过该表的读写配额

RESOURCE_NOT_FOUND(9) : 所指定的表不存在

限制

limit 值的范围为 (0, 1000]

limit数值设置过大会对服务器造成过大的压力,但是如果limit设置过小会增加访问服务器的频率

注意

可以选择使用主键(indexName不指定表示通过主键查询) 和二级索引查询。扫描可以指定查询范围,不指定时表示全表扫描。 查询范围定义的区间是[startKey, stopKey), 即两者全部属性都指定且相同时 查询的范围为空。其中startKey和stopKey可以只指定主键或者对应索引的部分属性(必须为前缀),指定 前缀时,查询范围的区间为 [startKey前缀 + 后缀可能的最小值, stopKey前缀 + 后缀可能的最大值 + 1)。例如, startKey = {userId = "user1"}, stopKey = {userId = "user1"} 表示查询user1下的所有笔记

扫描操作还可以指定过滤条件,需要注意的是,被条件过滤掉的记录也要计算读配额(根据索引类型 记1个或2个读配额)。过滤条件的语法类似SQL的Where语句。需要注意,属性不存在表示值为null, 除isnull和notnull操作符之外的所有其他表达式和函数调用结果都为null,如果表达式最终的值为null,则表达式的计算结果为false。

如果定义了哈希分布,跨实体组进行扫描需要先分别确定在每个哈希桶中的范围分布,再分别对每个哈希桶进行局部扫描,最后对所有桶内扫描结果进行归并排序, 因此会 引入较大性能开销,建议谨慎使用。 注:这种场景建议用户采用结构化存储MapReduce API MapReduce分布式计算框架将上述步骤分布 到多台机器并行执行,从而极大提高扫描性能。

扫描的三种方式

scan

扫描获得指定的startKey到stopKey之间的数据, limit中设置的数值为返回的最大数据量

以下两种情况返回数据量不等于limit

  • 用户读quota不足,发生throughput throttle
  • 已经扫完了最后的数据

示例

$scan = new ScanRequest(array(
  "tableName" => $tableName,
  "indexName" => "mtime",
  "startKey" => array(
    "userId" => DatumUtil::datum("user1"),
  ),
  "stopKey" => array(
    "userId" => DatumUtil::datum("user1"),
  ),
  "condition" => "title REGEXP '.*[0-5]' AND noteId > 5",
  "attributes" => array("noteId", "title", "mtime"),
  "limit" => 50 // 每次rpc返回的最大记录条数
));
$tableClient->scan($scan)

scanAll

scanAll是scan的一种实现,主要解决发生quota不足时返回不足limit的问题

只有一种情况返回数据量不足limit:

  • 已经扫完了最后的数据
注意:scanAll在遇到quota不足时会不断重试直到获取到limit指定的数据量才会返回到客户端,因此对于需要即时获取数据的场景不建议使用

示例

$scan = new ScanRequest(array(
  "tableName" => $tableName,
  "indexName" => "mtime",
  "startKey" => array(
    "userId" => DatumUtil::datum("user1"),
  ),
  "stopKey" => array(
    "userId" => DatumUtil::datum("user1"),
  ),
  "condition" => "title REGEXP '.*[0-5]' AND noteId > 5",
  "attributes" => array("noteId", "title", "mtime"),
  "limit" => 50 // 每次rpc返回的最大记录条数
));
$tableClient->scanAll($scan)

TableScanner

TableScanner是一种机制,一般情况下scan结束后需要判断scan返回的NextStartKey进行下一次scan,而TableScanner则可以在设置好scan参数后不断调用next获取后续的数据.

示例

$scan = new ScanRequest(array(
  "tableName" => $tableName,
  "indexName" => "mtime",
  "startKey" => array(
    "userId" => DatumUtil::datum("user1"),
  ),
  "stopKey" => array(
    "userId" => DatumUtil::datum("user1"),
  ),
  "condition" => "title REGEXP '.*[0-5]' AND noteId > 5",
  "attributes" => array("noteId", "title", "mtime"),
  "limit" => 50 // 每次rpc返回的最大记录条数
));

$scanner = new TableScanner($tableClient, $scan);

foreach ($scanner->iterator() as $k => $v) {
  echo "$k: " . DatumUtil::value($v['noteId'])
    . " [" . DatumUtil::value($v['title']) . "] "
    . DatumUtil::value($v['mtime']) . "\n";
}