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

时间:2013-09-19 16:10:53

标签: node.js sqlite

我有一个适度的Node.js脚本,它通过API从维基百科中提取数据并将其存储在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 个答案:

答案 0 :(得分:21)

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

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