网站搜索

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 个请求。