为啥 Sequelize 在 3120 条记录后会暂停?

Posted

技术标签:

【中文标题】为啥 Sequelize 在 3120 条记录后会暂停?【英文标题】:Why does Sequelize pauze after 3120 records?为什么 Sequelize 在 3120 条记录后会暂停? 【发布时间】:2018-04-13 15:01:39 【问题描述】:

我有一个用 Nodejs 编写的系统,首先必须将记录从非常大的 csv 文件导入数据库。使用Sequelize 作为我的 ORM,我创建了一个简单的模型,如下所示:

"use strict";
const Sequelize = require('sequelize');
const sequelize = new Sequelize('mm', 'root', 'password', 
    host: 'localhost',
    dialect: 'mysql',
    logging: true,
    pool: max: 5, min: 0, idle: 100000,
);
const Index = sequelize.define('index', 
    value: type: Sequelize.FLOAT
);

然后我编写了以下代码来循环文件中的行,解释这些行,并将它们写入数据库:

let readline = require('readline');
let moment = require('moment');

let lineReader = readline.createInterface(
    input: require('fs').createReadStream('files/price_index.csv')
);

lineReader.on('line', function (line) 
    let splitted = line.split(',');
    let dt = moment(parseInt(splitted[0]));
    let value = parseFloat(splitted[1]);
    console.log(dt.format(), value);
    Index.create(value: value, createdAt: dt);
);

这工作正常,但每 3120 条记录后它会暂停大约 3 秒。我尝试了 sqlite 和 mysql,但它总是在恰好 3120 条记录后暂停。

看到 Sequelize 也在这 3120 条记录之后开始记录插入查询,我认为这种行为的原因是某种缓存机制,它将所有查询放在一个队列中,直到它无事可做,或者如果它达到了 3120 条记录的神奇查询缓存限制。

我尝试在 Sequelize 的初始化中增加 pool.max 数字,但这似乎没有任何区别。

谁能确认我的缓存想法,或者解释一下这种行为的真正原因是什么?我可以以某种方式改变这种行为,使其具有一致的吞吐量吗?欢迎所有提示!

【问题讨论】:

【参考方案1】:

我认为 3120 行将是 the high water mark for the createReadStream buffer which is 64KiB。当缓冲区已满时,节点将停止读取。

看起来 3120 line 事件都在同一个 Node 事件滴答上运行,因此您处理了 3120 行,并为下一个滴答安排了 3120 个异步 Index.create 调用。因此,您最终需要在每一侧进行大量处理。要么读取和调度查询,要么处理大量已调度的查询。

当 3120 line 事件函数完成时,会发生一些垃圾收集,并且预定的 3120 续集 create 调用有机会完成它们的工作。这是数据中的“暂停”,但 Node 仍在处理。所有create 调用都需要几秒钟才能完成,然后进行更多的垃圾收集并返回到下一个csv 数据块以及所有line 事件。这个过程就这样来回进行。

在一个包含 10000 行的 csv 文件中,我看到在读取所有 10000 行 csv 数据并安排插入之前,可以运行大约 3 个查询。

一致的吞吐量

您可能希望使用具有较小块的Readable Stream。然后根据 sequelize 插入完成来阻止读取。您可能需要对自己进行线路处理,而不是使用readline。如果 csv 文件适合内存,只需读取整个内容,因为调度会更容易。

也许使用queue 之类的东西来管理插入,允许您的续集池max 作为concurrency。然后一旦队列的length 足够低,允许再次读取。

我不知道最终结果是否会更快,但可能会非常相似。

【讨论】:

以上是关于为啥 Sequelize 在 3120 条记录后会暂停?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我在 put 请求中的更新会覆盖 Sequelize 中的整个记录​​?

使用 sequelize 和 nodejs 更新多条记录?

Sequelize - 如何提取具有 1 个关联记录的记录并按关联记录属性排序

NodeJS/Sequelize/MySQL - 为啥需要 postgres 依赖项?

Sequelize string 不是函数错误,为啥?

为啥 sequelize.sync() 不同步表,除非我将模态导入文件?