我有一项小任务,每分钟运行一次,并在具有近3000行的表中执行扫描:
async execute (dialStatus) {
if (!process.env.DIAL_TABLE) {
throw new Error('Dial table not found')
}
const params = {
TableName: process.env.DIAL_TABLE,
FilterExpression: '#name = :name AND #dial_status = :dial_status AND #expires_on > :expires_on',
ExpressionAttributeNames: {
'#name': 'name',
'#dial_status': 'dial_status',
'#expires_on': 'expires_on'
},
ExpressionAttributeValues: {
':name': { 'S': this.name },
':dial_status': { 'S': dialStatus ? dialStatus : 'received' },
':expires_on': { 'N': Math.floor(moment().valueOf() / 1000).toString() }
}
}
console.log('params', params)
const dynamodb = new AWS.DynamoDB()
const data = await dynamodb.scan(params).promise()
return this._buildObject(data)
}
我面临有关dynamodb的读取单位和超时的问题。现在,我正在使用50个读取单元,与RDS相比,它变得越来越昂贵。
扫描功能上使用的属性名称不是我的主键:name
是二级索引,而dial_status
是json上的普通属性,但是每一行都有此属性。
此作业每分钟运行一次以获取参数列表(即:如果我有10个参数,我将在一分钟内执行scan
这十次操作)。
我的表具有以下架构:
作业应根据名称和Dial_status获取所有项目,并且每次执行(每分钟)项目的数量限制为15个元素。对于每个元素,应将其放入要处理的SQS中。
我确实需要减少这些读取单位,但不确定如何优化此功能。我已经读过有关减小页面大小或避免扫描的信息。如果我没有主键并且想返回一组行,可以避免scan
的其他方法是什么?
关于如何修复此代码每分钟被调用10到15次的任何想法?
答案 0 :(得分:1)
我建议您使用以下项创建GSI(全球二级索引):
name_dialStatus
expiresOn
您已经猜到,哈希键的值是两个独立字段name
和dialStatus
的串联。
现在,您可以在此GSI上使用查询,因为它不会扫描所有表格,而是仅浏览您感兴趣的项目,所以效率更高:
async execute(dialStatus) {
if (!process.env.DIAL_TABLE) {
throw new Error('Dial table not found')
}
const params = {
TableName: process.env.DIAL_TABLE,
IndexName: 'MY_GSI_NAME',
// replace `FilterExpression`
// always test the partition key for equality!
KeyConditionExpression: '#pk = :pk AND #sk > :skLow',
ExpressionAttributeNames: {
'#pk': 'name_dialStatus', // partition key name
'#sk': 'expires_on' // sorting key name
},
ExpressionAttributeValues: {
':pk': { 'S': `${this.name}:${dialStatus || 'received'}` },
':skLow': { 'N': Math.floor(moment().valueOf() / 1000).toString() }
}
}
console.log('params', params)
// Using AWS.DynamoDB.DocumentClient() there is no need to specify the type of fields. This is a friendly advice :)
const dynamodb = new AWS.DynamoDB();
// `scan` becomes `query` !!!
const data = await dynamodb.query(params).promise();
return this._buildObject(data);
}
答案 1 :(得分:0)
始终建议根据访问模式设计动态表,以便使用键(primarykey / sortkey)轻松查询该表并避免昂贵的扫描操作。