【问题标题】:Why is my Sequelize query so slow? (nested-joins using findAll)为什么我的 Sequelize 查询这么慢? (使用 findAll 的嵌套连接)
【发布时间】:2020-04-15 23:02:25
【问题描述】:

我看到一个问题,即我的查询速度呈指数级增长,因为我在 Schedule 模型中包含了更多 DayAvailability 嵌套关联。目标是序列化 User 实例以包含所有关联的实例。

这是表结构:

// User model

const User = sequelize.define('user', {
    id: {
      type: DataTypes.UUID,
      primaryKey: true
    }
}, {});
});

User.associate = function (models) {
  User.hasOne(models.Schedule);
};
// Schedule model

const Schedule = sequelize.define('schedule', {
  id: {
    type: DataTypes.UUID,
    primaryKey: true
  },
  userId: DataTypes.UUID
}, {
  hooks: {
    async afterCreate(instance, options) {
      await instance.createMonday();
      await instance.createTuesday();
      await instance.createWednesday();
      await instance.createThursday();
      await instance.createFriday();
      await instance.createSaturday();
      await instance.createSunday();
    }
  }
});

Schedule.associate = function(models) {
  Schedule.belongsTo(models.User);
  Schedule.hasOne(models.DayAvailability, { as: 'Monday', foreignKey: 'scheduleId' });
  Schedule.hasOne(models.DayAvailability, { as: 'Tuesday', foreignKey: 'scheduleId' });
  Schedule.hasOne(models.DayAvailability, { as: 'Wednesday', foreignKey: 'scheduleId' });
  Schedule.hasOne(models.DayAvailability, { as: 'Thursday', foreignKey: 'scheduleId' });
  Schedule.hasOne(models.DayAvailability, { as: 'Friday', foreignKey: 'scheduleId' });
  Schedule.hasOne(models.DayAvailability, { as: 'Saturday', foreignKey: 'scheduleId' });
  Schedule.hasOne(models.DayAvailability, { as: 'Sunday', foreignKey: 'scheduleId' });
};
// DayAvailability model

const DayAvailability = sequelize.define('day_availability', {
  id: {
    type: DataTypes.UUID,
    primaryKey: true
  },
  scheduleId: DataTypes.UUID
}, {});

DayAvailability.associate = function(models) {
  DayAvailability.belongsTo(models.Schedule);
};

(为简洁起见,省略其他字段)

此设置确实按预期工作。我可以获得一个包含嵌套 Schedule 实例的 User 实例,但是包括嵌套在 Schedule 实例中的 DayAvailability 实例会导致查询速度非常慢。如果我从查询中省略了一些 DayAvailability 实例关联,它不会那么慢。

// User controller

const include = { model: Schedule, include: [
    { association: 'Monday' },  // only Monday - ~0.1 sec
    { association: 'Tuesday' },  // include Tues - ~0.5 sec
    { association: 'Wednesday' },  // include Wed - ~1.5 sec
    { association: 'Thursday' },   // include Thurs - 2+ sec
    { association: 'Friday' },
    { association: 'Saturday' },
    { association: 'Sunday' }   // include all - times out 
]};

await User.findOne({
  where: { id: '123' },
  include
});

关于为什么这个查询如此缓慢的任何想法?包含这样的嵌套关联不好吗?

感谢您的帮助。


编辑:这是从上述 Sequelize 函数生成的 SQL 查询。模型中的其他字段作为提示包含在 SQL 查询中。

https://gist.github.com/FilmCoder/0afba42ffefb8f1e483699eb7ca2ac3b

【问题讨论】:

  • Schedule.hasOne(models.DayAvailability, { as: 'Tuesday', foreignKey: 'scheduleId' }); Schedule.hasOne(models.DayAvailability, { as: 'Wednesday', foreignKey: 'scheduleId' }); ...看起来像重复的不必要的关联。他们将映射完全相同的记录
  • 看来你把7个表记录相乘所以总记录量很大!
  • @Anatoly 表示同意,但是如何在 Schedule 模型上创建七个不同的字段,每个字段都映射到 DayAvailability 模型实例?顺便说一句,我最终将这些字段中的每一个都设置为 JSON 而不是单独的模型。它运作良好,但我没有回答这个问题,因为它仍然让我感到困惑。
  • DayAvailability 中有多少条记录对应一个日程表 ID?根据星期几从 0 到 7?

标签: postgresql sequelize.js sequelize-cli


【解决方案1】:

我可以提供更多信息。 DayAvailability 记录将来可能会扩展为更多列,以包含更多信息,例如一个人可用的时间范围、他们所在的时区、他们当天开放程度的跟踪记录等。 .

每个日程表会有 7 条 DayAvailability 记录,因为“日程表”代表一周,而 DayAvailability 代表该周的某一天。

我们想知道我们是否对外键做了根本性的错误,有一种方法可以在关系数据库中有效地进行这项工作。

我会对此发表评论,但由于某种原因堆栈溢出不会让我这样做。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-07
    • 1970-01-01
    • 2011-10-07
    • 2021-03-12
    • 2011-03-11
    • 1970-01-01
    相关资源
    最近更新 更多