SequelizeJS 中的关联速度慢

问题描述 投票:0回答:3

我正在尝试诊断使用 SequlizeJS 作为 ORM 的 Express 应用程序中某些速度变慢的原因。我有一个模型与其他 2 个模型有 2x hasMany 和 hasOne 关系:

更新:我已经使用 classMethods#associate 函数在定义调用中进行了关联。

// Model1
classMethods: {
    associate: function(models) {
        Model1.hasMany(models.Model2);
        Model1.hasMany(models.Model3);
        Model1.hasOne(models.Model2, {as: 'next', foreignKey: 'model2_next'});
    }
}

// Model2
classMethods: {
    associate: function(models) {
        Model2.belongsTo(models.Model1, {foreignKey: 'model2_next'});
    }
}

如果我通过以下方式查询它们:

db.Model1.find({
    where: { /* Simple where statement */ },
    include: [
        db.Model2,
        db.Model3,
        { model: db.Model2, as: 'next' },
    ]
}).complete(function(err, data) {
    res.json(data);
});

可能需要 8-12 秒才能响应。但是,如果我单独查询 Model2 并使用 async 和 lodash 库手动合并它们:

async.parallel({
    model2: function(callback) {
        db.Model2.findAll({
            where: { /* Simple where statement */ }
        }).complete(callback)
    },
    model1: function(callback) {
        db.Model1.find({
            where: { /* Simple where statement */ },
            include: [
                db.Model3,
                { model: db.Model2, as: 'next' },
            ]
        }).complete(callback);
    }
}, function(err, data) {
    var response = data.model1.values;
    response.Model2 = data.model2.map(function(Model2){ return Model2.values });

    res.json(response);
})

需要 60-100 毫秒。

我尝试过从 MySQL 切换到 PostgreSQL,虽然 PostgreSQL 速度稍快一些,但速度提高了 2-3%!

是什么导致 Sequelize 花费的时间比拆分查询长得多?有没有办法可以加快速度?

mysql node.js postgresql sequelize.js
3个回答
20
投票

当您将 :M 关系添加到包含中时,Sequelize 会变慢。 :M 关系会导致 sql 结果中出现重复行,因此我们必须花时间对其进行重复数据删除并将其解析为模型。

为了获得最佳性能,您可以在包含中保留 :1 关系,但在单独的查询中执行 :M。

当然查询本身也可能很慢,但很可能是 Sequelize 开销的结果 - 尝试直接在数据库上运行查询。

(免责声明:Sequelize 核心开发人员)

您运行的是什么版本?您报告的初始数字听起来很高,但我们在进行一些优化之前就已经听说过这些数字,请尝试针对最新的 git master 进行测试。

我们一直致力于优化这些场景的代码,但将 20.000 行重复数据删除到 5.000 行始终需要一些 CPU 周期。


14
投票

对于您的

hasMany
包含(并在正确索引后),请考虑添加
separate: true,

它基本上并行执行

include
块,而不是顺序执行。

我的查询从 10 秒缩短到不到 200 毫秒:

include: [
    {
        model: MyModel,
        as: 'myModels',
        separate: true, // does magic; only with .hasMany associations
    },
]

文档: https://sequelize.org/docs/v7/querying/select-in-depth/#separate-eager-loading-queries


2
投票

在您的模型关联中,sequelizejs 不创建索引

{foreignKeyConstraint: true} 添加到所有关联中。

Model1.hasMany(models.Model2, {foreignKeyConstraint: true});
Model1.hasMany(models.Model3, {foreignKeyConstraint: true});
Model1.hasOne(models.Model2, {as: 'next', foreignKey: 'model2_next', foreignKeyConstraint: true});
Model2.belongsTo(models.Model1, {foreignKey: 'model2_next', foreignKeyConstraint: true});
© www.soinside.com 2019 - 2024. All rights reserved.