【发布时间】:2018-12-10 20:45:26
【问题描述】:
我有一个小作业,每分钟运行一次,并在一个有近 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 相比,它变得越来越贵。
scan 函数中使用的属性名称不是我的主键:name 是二级索引,dial_status 是我的 json 上的普通属性,但每一行都有这个属性。
此作业每分钟运行一次,以获取参数列表(即:如果我有 10 个参数,我将在一分钟内执行此scan 10 次)。
我的表具有以下架构:
- 电话(PK 哈希)
- 配置:字符串格式的 JSON;
- dial_status 字符串;
- expires_on:TTL 号;
- 名称:字符串
- 来源:字符串;
作业应根据 name 和 dial_status 获取所有项目,并且每次执行(每分钟)项目的数量限制为 15 个元素。对于每个元素,都应该在 SQS 上排队进行处理。
我确实需要减少这些读取单元,但我不确定如何优化此功能。我读过有关减小页面大小或避免扫描的信息。如果我没有主键并且我想返回一组行,我有哪些替代方法可以避免 scan?
知道如何修复此代码,使其每分钟被调用 10-15 次吗?
【问题讨论】:
-
您应该告诉我们更多关于您的表架构以及这项工作的用途。
-
检查编辑,请@MatthewPope
-
你是如何处理事情的?您是否希望每个项目只处理一次,无论何时更新、每天还是其他?
-
正是一个。处理该项目时,它应该更新列
dial_status。项目由另一个函数处理,完成后应该更新 dynamodb。如果可能的话,我可以检索项目,删除并发送到 sqs。 -
如果您需要一次性处理,那么您应该使用 DynamoDB Streams。正如您正确识别的那样,任何类型的查询或表扫描都无法很好地扩展。查看aws.amazon.com/blogs/database/…
标签: javascript node.js amazon-dynamodb