javascript - PouchDB 通过 websql 插入 4800 个文档慢了大约 3 倍

标签 javascript pouchdb

一直在探索 pouch db 的使用,因此我们可以利用它的离线同步而不是自己做。我们有一个 cordova 应用程序,它从 REST API 中提取数据并将其保存到 Web sql 存储中。其中一部分是各种商店的大约 5000 个物理位置。我在 cordova 应用程序上计时,我们在大约 11 秒内下载商店并保存它们,以及另一个项目信息请求。仅将这 5k 条记录保存为 pouch 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 人的 list 分成了多个部分。我玩了几个不同的尺寸。 300 和 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);
  });
}

最佳答案

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

5000 份文件很多。我对 PouchDB 的经验是,bulkDocs() 有一个最佳点(取决于您的文档大小),它可能远小于 5000。这适用于 IndexedDB 和 WebSQL。

很可能您可以通过批处理 100-500 block 来加速您的代码,同时使用 limitstartkeyallDocs() 中分页>(即使用 this blog post 中描述的策略),然后使用 bulkDocs() 一次插入 100-500。

为了证明我没有撒谎,你可以查看http://npm-browser.com/ ,它在单个 bulkDocs() 中每批插入大约 500 个来自 npm 的元数据文档,并且绝对不会每批花费 7 秒。 (大部分时间花在等待网络下载文件上。)

关于javascript - PouchDB 通过 websql 插入 4800 个文档慢了大约 3 倍,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30536760/

相关文章:

javascript - 为当前图像/幻灯片分配类别

pouchdb - 使用参数进行PouchDB查询

javascript - RxDb,使用默认索引时无法对字段 XXX 进行排序

javascript - pouchDB 并按日期或日期范围查询

javascript - 全局执行上下文是否可以弹出执行堆栈?

javascript - 如何使用 javascript 判断浏览器是否支持网页字体?

javascript - 使用 PouchDB 的实时 Web 应用程序

couchdb - 无法从 PouchDB 检索值

javascript - 选择标签选项中的 jQuery 警报文本

javascript - 创建 html 表单将下载链接发送到给定的电子邮件地址?