在前面章节我们讲到Scan命令会扫描全表,并且返回最多1MB数据。Scan
和Query
类似,不同之后我们是扫描的全表,而不是一个Item Collection
,另外在Scan中不能传入Key Condition表达式。但可以使用Filter
表达式来减少返回结果的数量
例如,查询Reply表中所有User A发表的评价:
aws dynamodb scan \
--table-name Reply \
--filter-expression 'PostedBy = :user' \
--expression-attribute-values '{
":user" : {"S": "User A"}
}' \
--return-consumed-capacity TOTAL
在返回结果里看到:
"Count": 3,
"ScannedCount": 4,
这表明Scan
扫描了全表的4条记录,但是Filter表达式筛选出来3条满足条件的
有时候Scan返回的结果条目非常多,如果想对它分页的话,可以使用--max-items
来指定返回结果的数量,使用NextToken
来查询后面的结果。例如上面的查询返回了3条结果,我们将最大结果数量设置为2,这样总共有两页数据,第一次查询:
aws dynamodb scan \
--table-name Reply \
--filter-expression 'PostedBy = :user' \
--expression-attribute-values '{
":user" : {"S": "User A"}
}' \
--max-items 2 \
--return-consumed-capacity TOTAL
我们看到在返回结果里有个NextToken
字段:
所以可以再次调用scan,在starting-token
参数传入NextToken
:
aws dynamodb scan \
--table-name Reply \
--filter-expression 'PostedBy = :user' \
--expression-attribute-values '{
":user" : {"S": "User A"}
}' \
--max-items 2 \
--starting-token eyJFeGNsdXNpdmVTdGFydEtleSI6IG51bGwsICJib3RvX3RydW5jYXRlX2Ftb3VudCI6IDJ9 \
--return-consumed-capacity TOTAL
如果有LastEvaluatedKey
,则进行后面的遍历;如果LastEvaluatedKey
为空,则所有数据已全部取回。
例如:
import boto3
import json
import time
dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
table = dynamodb.Table("employees")
response = table.scan(Limit=100)
data = response['Items']
queryCount=1
for item in data:
print(item['PK'])
print("---------------------", queryCount,time.time())
while 'LastEvaluatedKey' in response:
print(response['LastEvaluatedKey'])
queryCount += 1
response = table.scan(ExclusiveStartKey=response['LastEvaluatedKey'],Limit=100)
data = (response['Items'])
for item in data:
print(item['PK'])
print("--------------------------",queryCount,time.time())
每次scan是否要扫全表?答案是否,因为每次传入了LastEvaluatedKey
,这个Key其实是PK+SK,有了这两个字段,就可以迅速定位到起始位置。
例如当Limit=10时,扫描一个很大的表,每次返回结果都在几十毫秒,这说明不是全表扫描。