PouchDB在websql上插入4800个文件的速度要慢3倍

时间:2015-05-29 18:36:35

标签: javascript pouchdb

一直在探索使用pouch db,以便我们可以利用其离线同步而不是自己做。我们有一个cordova应用程序,它从REST API中提取数据并将其保存到Web sql存储中。其中一部分是各种商店的约5k个物理位置。我在cordova应用程序上计时,我们下载商店&在大约11秒内保存它们以及另一个项目信息请求。只需将这些5k记录保存为包db中的文档需要30秒。不计算请求时间。

这就是我的所作所为:

let db = PouchProxy.getDB();
this.render("loading", { message: "Saving locations" });
// stores from api
let stores = res.stores;
let docs = [];
// check for saved stores, checking ids that start with store_
db.allDocs({ include_docs: true, startkey: 'store_', endkey: 'store_\uffff' }).then((results) => {
  // go through saved stores
  for (let row of results.rows) {
    let doc = row.doc;
    // get the number id. The _id is simply 'store_idnumfromapi'
    let id = parseFloat(doc._id.split('store_')[1]);
    if (isNaN(id)) {
      throw "Cannot be NaN";
    }
    // iterate through stores from api
    for (var i = 0; i < stores.length; i++) {
      let store = stores[i];
      // find store and local record
      if (store.id === id) {
        // sets the _id and other properties from the store api object to a new object
        let map = PouchProxy.storeToDocMap(store);
        // set revision
        map._rev = doc._rev;
        docs.push(map);
        stores.splice(i, 1);
        break;
      }
    }
  }

  // go through remaining stores and push to docs set
  for (let store of stores) {
    docs.push(PouchProxy.storeToDocMap(store));
  }

  // save all the things
  console.log(Date.now());
  return db.bulkDocs(docs);
}).then(() => {
  // this the second time stamp i use to get the 30 seconds
  console.log(Date.now());
  // calculate geolocation stuff
  for (let store of docs) {
    store.distance = this.distanceBetweenPoints(store, { lat: position.coords.latitude, long: position.coords.longitude });
  }
  docs.sort((a, b) => {
    return b.distance - a.distance;
  });
  this.render("store-list", { stores: docs.slice(0, 19) });
}).catch(function (err) {
  console.log(err);
});

希望代码足够清晰。我考虑过为商店切换到一个文档,但后来我觉得单个查找会更加困难和昂贵。

编辑,修改代码。表现实际上更糟:(

根据建议,我将5000列表分成了块。我玩了几个不同的尺寸。 300&amp; 500,两者的保存数据非常相似。以下是它现在的样子:

saveLocations(db, stores) { // position
  var storeSlices = [];
  stores.sort(function (a, b) {
    return a.id - b.id;
  });
  stores.eachSlice(300, (slice) => {
    storeSlices.push(slice);
  });

  console.log(Date.now());
  this.commitBatch(db, storeSlices, 0, () => {
    console.log(Date.now());
    // this.sortAndRenderStores(docs, position);
    this.render("store-list", { stores: [] });
  });
}

commitBatch(db, slices, index, callback) {
  let stores = slices[index];
  db.allDocs({ include_docs: true, startkey: 'store_' + stores[0].id, endkey: 'store_' + stores[stores.length - 1].id }).then((results) => {
    let docs = [];
    for (let row of results.rows) {
      let doc = row.doc;
      let id = parseFloat(doc._id.split('store_')[1]);
      if (isNaN(id)) {
        throw "Cannot be NaN";
      }
      // iterate through stores from api
      for (var i = 0; i < stores.length; i++) {
        let store = stores[i];
        // find store and local record
        if (store.id === id) {
          let map = PouchProxy.storeToDocMap(store);
          // set revision
          map._rev = doc._rev;
          docs.push(map);
          stores.splice(i, 1);
          break;
        }
      }
    }

    // go through remaining stores and push to docs set
    for (let store of stores) {
      docs.push(PouchProxy.storeToDocMap(store));
    }

    db.bulkDocs(docs).then(() => {
      index++;
      if (index < slices.length) {
        this.commitBatch(db, slices, index, callback);
      }
      else {
        callback();
      }
    });
  }).catch(function (err) {
    console.log(err);
  });
}

1 个答案:

答案 0 :(得分:3)

我的猜测是,这里的问题是你要一次性将所有文档读入内存(或至少每个文档都以store_为前缀,这是allDocs()正在做的事情),然后你也会一次性写出所有这些文件。

5000个文件很多。我对PouchDB的体验是bulkDocs()有一个最佳位置(取决于你的文档大小),它可能小于5000.这适用于IndexedDB和WebSQL。

您最有可能通过批量处理100-500块来加速代码,同时使用allDocs()limitstartkey中进行分页(即使用{{3}中描述的策略}}),然后使用bulkDocs()一次插入100-500。

作为我没有反复的证据,您可以查看this blog post,它会在一个bulkDocs()中每批次从npm插入大约500个元数据文档,并且绝对不会每批需要7秒。 (花费的大部分时间都在网络上等待下载文件。)