9

我有一个数据库(300MB 和 42,924 个文档),包含来自大约 200 个用户的大约 20 种不同类型的文档。文档的大小范围从几个字节到许多 KiloBytes(150KB 左右)。

卸载服务器后,以下复制过滤器功能大约需要 2.5 分钟才能完成。加载服务器时,需要 >10 分钟。

任何人都可以评论这些时间是否是预期的,如果不是,建议我如何优化事情以获得更好的性能?

function(doc, req) {
    acceptedDate = true;
    if(doc.date) {
        var docDate = new Date();
        var dateKey = doc.date;
        docDate.setFullYear(dateKey[0], dateKey[1], dateKey[2]);

        var reqYear = req.query.year;
        var reqMonth = req.query.month;
        var reqDay = req.query.day;
        var reqDate = new Date();
        reqDate.setFullYear(reqYear, reqMonth, reqDay);

        acceptedDate = docDate.getTime() >= reqDate.getTime();
    }

    return doc.user_id && doc.user_id == req.query.userid && doc._id.indexOf("_design") != 0 && acceptedDate; 
}
4

1 回答 1

12

过滤复制工作缓慢,因为每个获取的文档都会运行复杂的逻辑来决定是否复制它:

  1. CouchDB 获取下一个文档;
  2. 因为必须应用过滤功能,所以文档被转换为 JSON;
  3. JSON 化的文档通过 stdio 到查询服务器;
  4. 查询服务器处理文档并从 JSON 中解码;
  5. 现在,查询服务器查找并运行您的过滤器函数,该函数返回truefalse值给 CouchDB;
  6. 如果结果是true要复制文档;
  7. 转到第 1 页并循环查看所有文档;

对于未过滤的复制,请使用此列表,丢弃 p.2-5 并让 p.6 始终有true结果。这种开销会减慢整个复制过程。

为了显着提高过滤复制速度,您可以通过Erlang native server使用 Erlang 过滤器。它们在 CouchDB 中运行,不通过任何 stdio 接口,也没有应用 JSON 解码/编码开销。

注意,Erlang 查询服务器不像 JavaScript 那样在沙箱中运行,因此您需要真正信任您使用它运行的代码。

另一种选择是优化您的过滤器功能,例如减少对象创建、方法调用,但实际上您不会因此获得太多好处。

于 2012-11-02T13:06:15.973 回答