query操作

Query

  • PartitionKey必须是=
  • SortKey可以是任意比较符。
  • 最多返回1MB数据。
  • 可以分页。

image-20220826114209592

query分表

注意,此节概念适用于query操作。scan机制不一样。

如果查询时没有传入pagination字段,那么最多返回1MB数据

image-20210204143530707


可以使用分页机制, 遍历取出所有结果:

image-20210204143959124


query时不能并发查询,因为只有取到了lastEvaluatedKey,才能进行下一次查询。

image-20210204144315918


Scan分页

Scan操作和上面一样,检查Scan返回的结果。如果有LastEvaluatedKey,则进行后面的遍历,如果LastEvaluatedKey为空,则所有数据已全部取回。


实践:使用scan分页扫全表

import boto3
import json
import time

dynamodb = boto3.resource('dynamodb', region_name='us-east-1')

def lambda_handler(event, context):
    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())


lambda_handler(1, 2)

image-20210204184530113

  • 每次scan是否要扫全表?答案否,因为每次传入了LastEvaluatedKey,这个Key其实是PK+SK,有了这两个字段,就可以迅速定位到起始位置。想了一下午终于想通了这点。测试的时候也证明了,当Limit=10时,扫描一个很大的表,每次返回结果都在几十毫秒,这说明不是全表扫描。
  • 如果没有设置SK,则LastEvaluatedKey是PK。

其他要注意的点

RCU根据item大小来计算,而不是返回的数据大小(比如使用Projection筛选出了部分数据)。或者scan时使用filter过滤了不满足条件的数据。


如果在Scan时使用了ConsistRead,那么在Scan过程中,所有的写操作都会被DDB Streams记录下来,当Scan完成后,才会将写操作应用到表上。