SequelizeJS中的缓慢关联

时间:2014-04-11 14:05:11

标签: mysql node.js postgresql sequelize.js

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

更新:我使用classMethods #association函数在define调用中建立了关联。

// 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& amp;手动合并它们。 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比分割查询花费的时间更长,有没有办法让我加快速度?

3 个答案:

答案 0 :(得分:6)

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

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

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

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

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

我们一直在努力优化这些方案的代码,但重复数据删除20.000行到5.000行总是需要一些cpu周期。

答案 1 :(得分:1)

在您的模型关联中,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});

答案 2 :(得分:1)

对于您的 hasMany 包含(并在正确编制索引后),请考虑添加 separate: true,

它基本上是并行执行 include 块,而不是顺序执行。

我有一个查询从 10 秒到不到 200 毫秒:

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

文档:https://sequelize.org/master/class/lib/model.js~Model.html