Рекомендации по использованию SQLite3 + Node.js
У меня есть скромный Node.js script, который извлекает данные из Википедии через API и сохраняет их в базе данных SQLite. Я использую этот node-sqlite3 модуль.
В некоторых случаях я собираю данные по 600 000 статей и храня некоторые метаданные о каждом из них в строке в db. Статьи извлекаются группами по 500 из API.
Запрос, который извлекает объект JSON с данными в 500 статьях, передает объект этому обратному вызову:
//(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 намного быстрее, чем записываются в БД, хотя это не невыносимо медленно. Но избиение БД с помощью индивидуальных команд INSERT
с числами 600K кажется неуклюжим.
UPDATE:
В соответствии с принятым ответом это работает для 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
Когда вы делаете несколько вставок в базу данных SQLite, вам необходимо обернуть коллекцию вставок в транзакцию. В противном случае SQLite будет ожидать, что дисковые планшеты будут полностью вращаться для каждой вставки, в то время как он выполняет проверку чтения после записи для каждой записи, которую вы вставляете.
При скорости вращения 7200 об/мин требуется около 1/60 секунды для дискового диска снова, что является вечностью в компьютерном времени.