node.js - 加速 sequelize ORM 中的查询
我正在创建一个具有以下结构的健身应用程序:
用户有一个计划,计划有许多训练,训练有许多动作(多对多),训练有许多超级组,超级组有许多动作(多对多)。
所以我有一个算法,它创建一个包含9个训练的程序,每个训练有6-8个练习,对于每个练习,我从数据库中找到一个合适的并将其与训练关联保存。所以总体上,我创建了一个程序、9个训练和54-72个练习。
然而,整个过程需要20-25秒。这太久了。我尝试过使用raw和attributes选项。
这是创建一次锻炼的算法。我在这里检查不同的锻炼选项,但这不应该大大减慢过程。你不需要了解模型中的字段。我会非常感激任何帮助,谢谢!!!
public static async generateWorkout(body: WorkoutRequestApi, currentDay: number, workoutCounter: number) {
let existing: string[] = [];
let exercise: ExercisesModels | null;
const workoutId: string = randomUUID();
await Workout.create({
uuid: workoutId,
isFinished: false,
programId: body.progId,
type: body.programOptions.types[workoutCounter]
})
await Superset.create({uuid: workoutId})
for (let i = 0; i < body.programOptions.workouts[currentDay].length; i++) {
console.log("DAY: " + currentDay + " I: " + i)
const currentExerciseModel = body.programOptions.workouts[currentDay][i];
let unique: boolean = false;
console.log(currentExerciseModel)
if (currentExerciseModel.isSuperset) {
while (!unique) {
const firstExercise: ExercisesModels | null = await ExerciseUtil.findWorkoutExercise(currentExerciseModel, currentExerciseModel.hasPriority ? true : false)
const secondExercise: ExercisesModels | null = await ExerciseUtil.findFixedExercise(body.programOptions.workouts[currentDay][i + 1])
if (firstExercise && secondExercise) {
if (!existing.includes(firstExercise.uuid)) {
unique = true
existing.push(firstExercise.uuid)
existing.push(secondExercise.uuid)
console.log("INSERTING " + firstExercise.uuid + " and " + secondExercise.uuid)
exercise = await this.modelToExercises(firstExercise, {
reps: currentExerciseModel.reps,
sets: currentExerciseModel.sets,
order: i
}
)
console.log(exercise)
await SupersetExercise.create({
ExerciseUuid: exercise.uuid,
SupersetUuid: workoutId
})
exercise = await this.modelToExercises(secondExercise, {
reps: currentExerciseModel.reps,
sets: currentExerciseModel.sets,
order: i+1
}
)
await SupersetExercise.create({
ExerciseUuid: exercise.uuid,
SupersetUuid: workoutId
})
}
}
}
i++;
if (i >= body.programOptions.workouts[currentDay].length)
break
} else {
if (currentExerciseModel.isFixed === true) {
console.log("FIXED EXERCISE")
exercise = await ExerciseUtil.findFixedExercise(currentExerciseModel);
if (exercise) {
console.log("FOUND FIXED" + exercise.name)
exercise = await this.modelToExercises(exercise, {
reps: currentExerciseModel.reps,
sets: currentExerciseModel.sets,
order: i
}
)
try {
await WorkoutExercise.create({
WorkoutUuid: workoutId,
ExerciseUuid: exercise.uuid
});
} catch (e) {
console.log(<Error>e)
}
}
} else {
while (!unique) {
exercise = await ExerciseUtil.findWorkoutExercise(currentExerciseModel, i <= 2)
if (exercise) {
if (!existing.includes(exercise.uuid)) {
unique = true
existing.push(exercise.uuid)
exercise = await this.modelToExercises(exercise, {
reps: currentExerciseModel.reps,
sets: currentExerciseModel.sets,
order: i
})
try {
await WorkoutExercise.create({
WorkoutUuid: workoutId,
ExerciseUuid: exercise.uuid
});
} catch (e) {
console.log(<Error>e)
}
}
}
}
}
}
}
答案#1
碰巧的是,你的代码在每次 while 循环交互中会访问数据库 3 次。做一些基础计算,这大概需要 300 毫秒(每次 git 100 毫秒),对于每 3 条记录,你大约会等待 1 秒。
我的建议是在白色之前获取那些记录,然后在内存中读取它们。我不是 Superset 专家,但这是基本的数据库输入输出。
每次访问数据库时,你可以计算平均至少有100毫秒的延迟,有时甚至更多。
我知道一开始这似乎没有道理,因为在这种情况下你会节省内存。如果你能只过滤出你需要的记录放入那个数组。有人曾经告诉我:“调优更多的是艺术而不是逻辑”。哈哈。
一个包含所需所有信息的单一请求大约需要 120 毫秒(比单个请求多),但它可以避免过程中其他 1000 个请求。