使用 SQLite3 + Node.js 的最佳实践

Posted

技术标签:

【中文标题】使用 SQLite3 + Node.js 的最佳实践【英文标题】:Best practices for using SQLite3 + Node.js 【发布时间】:2013-09-24 20:12:11 【问题描述】:

我有一个适度的 Node.js 脚本,它通过 API 从 Wikipedia 中提取数据并将其存储在 SQLite 数据库中。我正在使用这个node-sqlite3 模块。

在某些情况下,我会提取超过 600,000 篇文章的数据,并将关于每篇文章的一些元数据连续存储在数据库中。从 API 中以 500 篇为一组检索文章。

使用 500 篇文章的数据检索 JSON 对象的请求将对象传递给此回调:

// (db already instantiated as 'new sqlite.Database("wikipedia.sqlite");')

function callback(articles) 
    articles.forEach(function (article) 
        db.run(
            "INSERT OR IGNORE INTO articles (name, id, created) VALUES (?,?,?)", 
            [
                article["title"], 
                article["pageid"], 
                article["timestamp"]
            ]
        );
    );

这些模块默认并行运行,但 node-sqlite3 的文档包含一个串行操作示例,如下所示:

db.serialize(function () 
    db.run("CREATE TABLE lorem (info TEXT)");

    var stmt = db.prepare("INSERT INTO lorem VALUES (?)");
    for (var i = 0; i < 10; i++) 
        stmt.run("Ipsum " + i);
    
    stmt.finalize();

我试图模仿这一点,但几乎没有发现性能差异。我做错了吗?现在,从 API 中检索数据的速度比写入数据库的速度快得多,尽管速度还不算慢。但是用 600K 个单独的 INSERT 命令来攻击数据库感觉很笨拙。

更新: 根据接受的答案,这似乎适用于 node-sqlite3,而不是原生解决方案。 (见Issue)。

db.run("BEGIN TRANSACTION");
function callback(articles) 
    articles.forEach(function (article) 
        db.run(
            "INSERT OR IGNORE INTO articles (name, id, created) VALUES (?,?,?)",
            [
                article["title"],
                article["pageid"],
                article["timestamp"]
            ]
        );
    );

db.run("END");

【问题讨论】:

+1 表示“开始交易”的想法。您可以根据数据库大小来提高速度的其他方法是安装 ram 驱动器并从那里运行数据库。在 Windows 上,我过去使用过 OSFMunt,效果非常好。 抱歉,您能否解释一下更新部分,因为我不明白。你为什么要在调用 db.run 之间声明一个函数?有错吗? 【参考方案1】:

当您对 SQLite 数据库进行多次插入时,您需要将插入的集合包装到事务中。否则,SQLite 将等待磁盘盘片在每次插入时完全旋转,同时对您插入的每条记录进行读写验证。

在 7200 RPM 时,磁盘盘片再次旋转大约需要 1/60 秒,这是计算机时间的永恒。

【讨论】:

这是一个有趣的视角。无论平台(例如电话、服务器)如​​何,SQLite 都是这样工作的吗?即使插入的集合不相互依赖,仍然需要一个事务来减少总插入时间? @Joyce:事务推迟写后读验证,直到所有插入完成。这就是它加快速度的方式;您不必在每次插入后等待盘片旋转。插入是否相互关联并不重要。

以上是关于使用 SQLite3 + Node.js 的最佳实践的主要内容,如果未能解决你的问题,请参考以下文章

使用 node.js 检查数据是不是包含在 SQLite3 数据库中

如何在 node.js 中使用 sqlite3 执行批量插入?

Node.js 说它不能加载 sqlite3 模块,但无论如何

如何使用node js同步读取sqlite3数据库?

markdown rest-api使用node.js和sqlite3

node.js 上的 Sqlite3 产生 SQLITE_ERROR