使用Node.JS,(Dynamo DB和Sequelize)
嘿那里,
我正在尝试解决以下统计报告数据的最佳方式,这些数据需要跟踪以实现长期可扩展性。原始架构师使用dynamoDB解决方案,因为它是No SQL,我们需要灵活地添加数据而不受架构的限制。但是,他将属性嵌套到列对象中,要求我们查询整个表,然后遍历结果,分别检查每一行以根据请求的搜索查询构建响应。
以下是最初存储在dynamoDB
中的示例report
对象
示例1
{
"boolData": null,
"datetime": 1490391013471,
"eventData": [
{
"eventType": 0,
"location": "-16.3, 2.1, -70.8",
"timestamp": 1490391033260
}
],
"floatData": {
"averageAltitude": 1.79624987,
"averageSpeed": 0,
"maxAltitude": 3.55,
"scorePercent": 0,
"topSpeed": 0
},
"intData": {
"altitudeViolations": 0,
"closeCalls": 0,
"crashCount": 1,
"distanceToNoFlyViolations": 0,
"lostLineOfSightViolations": 0,
"moduleId": 2010,
"moduleStatus": 0,
"resetCount": 0,
"sceneId": 1007,
"score": 0,
"tooCloseOrAbovePersonViolations": 0
},
"longData": {
"moduleCompleted": 1490391033260,
"moduleStartTime": 1490391023584,
"moduleTotalTime": 9676
},
"objecttype": 1,
"stringData": {
"name": "test",
"grade": "F",
"moduleName": "HorizontalFlight1",
"sceneName": "BasicTraining"
},
"userid": 1
}
由于上述原因,这显然不是存储数据的最佳方式,因为如果我想知道在特定模块或场景中发生的所有航班的averageAltitude
是什么,我会' d必须查询所有数据,然后遍历所有结果并检查嵌套在floatData
和intData
中的属性,并与查询中请求的信息进行比较以构建响应。
所以我的下一个想法是为什么不将所有数据存储在自己的列中,就像EXAMPLE 2
一样?我在Dynamo DB中使用此模式可以看到的唯一缺点是,行/项中允许的最大数据量为400KB,并且因为我们不知道将来要添加多少数据,这可能会导致缩放问题。解决方案只是限制返回的项目,并根据我们当前所知的项目大小对响应进行分页,并将其除以1mb扫描上限。
示例2
{
"boolData": null,
"datetime": 1490391013471,
"eventData": [
{
"eventType": 0,
"location": "-16.3, 2.1, -70.8",
"timestamp": 1490391033260
}
],
"averageAltitude": 1.79624987,
"averageSpeed": 0,
"maxAltitude": 3.55,
"scorePercent": 0,
"topSpeed": 0
"altitudeViolations": 0,
"closeCalls": 0,
"crashCount": 1,
"distanceToNoFlyViolations": 0,
"droneId": 0,
"lostLineOfSightViolations": 0,
"moduleId": 2010,
"moduleStatus": 0,
"resetCount": 0,
"sceneId": 1007,
"score": 0,
"tooCloseOrAbovePersonViolations": 0
"moduleCompleted": 1490391033260,
"moduleStartTime": 1490391023584,
"moduleTotalTime": 9676
"objecttype": 1,
"name": "test",
"grade": "F",
"moduleName": "HorizontalFlight1",
"sceneName": "BasicTraining"
"userid": 1
}
我正在考虑的另一个想法是将intData
,floatData
,stringData
和eventData
分隔到他们自己的发电机数据库表中,索引为{{ 1}}相应地关联它们,然后构造响应。但是,我不确定dynamo DB是否是为这种关联/关系目的而设计的,而且我非常确定使用RDS会导致我的第二个提议更快。
如果我将reportId
存储在Aurora / MySQL RDS中,并将EXAMPLE 1
,intData
,floatData
和stringData
字符串化以将其存储在对于eventData
表,他们各自的TEXT
或BLOB
列,我非常确定可扩展性的效率会大大降低。对数据进行字符串化会添加所有这些额外字节,即使它允许我们灵活地添加和删除要在这些列中跟踪的属性,我们仍然无法执行Reports
之类的查询,因为这需要我完全按照解析字符串化JSON的额外步骤做了我正在做的事情。我查询所有报告并迭代检查SELECT * REPORTS WHERE averageAltitude >= 1.5
属性averageAltitude,然后构建我的结果。因此,为了避免这种情况,使用以下模式为floatData
,intData
和floatData,
创建RDS表(仅显示intData示例目的)
intData
stringData
然后做一个Report.hasMany Association
id: {
type: DataTypes.INTEGER.UNSIGNED,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
name: {
type: DataTypes.STRING(191),
allowNull: false
},
value: {
type: DataTypes.INTEGER,
allowNull: false
}
似乎是一个非常实用的方法,可以很好地工作,因为我可以轻松地将数据包含在查询中,并且对于每个报告插入的intData,floatData的数量是不可知的。这是最优化的方法吗?这种方法会将Dynamo数据库表一起删除,但肯定看起来比将db.Report.hasMany(db.IntData, {
as: 'intData',
foreignKey: 'reportId',
constraints: false
});
,intData
等存储为floatData
列中的JSON字符串更为理想。我不确定从长远来看,这种方法是否具有成本效益的可扩展性,然后使用dynamo DB。我们希望尽可能推迟升级到大型RDS,查询报告绝对是最昂贵的电话。
感谢您的建议和意见。如果我完全错过一个比我建议的更好的解决方案,请告诉我一个替代解决方案。谢谢!