Couchdb超慢视图,100%cpu使用率

时间:2017-02-22 00:24:41

标签: couchdb

有一个帐户文档。这个文件有大约1k个席位。对于每个座位,我们会发出一份文件。当然,你会觉得这很慢。 map函数的运行方式如下:

function(doc) {
    if (doc.type == 'account') {
        doc.seats.map(function(seat) {
            emit(seat.userID, doc))
        } 
    }
}

然而,删除doc.seats,然后发出更小的文档似乎没有帮助。

function(doc) {
    if (doc.type == 'account') {
        doc.seats.map(function(seat) {
            delete doc.seats
            emit(seat.userID, doc))
        } 
    }
}

有谁理解为什么删除座位不会加速这个?我们可以加快速度的唯一方法是不发出doc对象,只发出一个id。

function(doc) {
    if (doc.type == 'account') {
        doc.seats.map(function(seat) {
            emit(seat.userID, doc.id))
        } 
    }
}

这是在沙发视图中循环播放doc数组的问题吗?

1 个答案:

答案 0 :(得分:5)

<强> tldr;

  1. 如果您关心表现,请使用永久视图
  2. doc从视图中是不可变的。你甚至无需复制就可以添加它。
  3. 发出_id并使用include_docs几乎总是比发出整个doc作为你的值更好。
  4. <强>解释

    以下是您的问题的几点,使用您的示例文档,其中包含一个名为1K条目的席位数组。

    在这里发布整个文档是一个坏主意。如果这是一个永久性视图(如果性能完全成问题,您应该始终使用它),您已经获得了一份doc副本,然后制作了1000份副本并通过seat.userID对它们编制索引。这不是有效的。它作为一个临时视图更糟糕,因为它会在每次调用视图时在内存中生成。

    AFAIK文档完全不可变,因为通过视图访问,因此您尝试删除席位字段的方式不起作用。因此,删除doc.seats不应该提供任何性能提升,因为您仍然要完成循环并创建1000份原始文档。但是,您可以制作一份没有包含席位的doc的深层副本,并通过emit传递它。

    例如:

    function(doc) {
      var doc_without_seats = JSON.parse(JSON.stringify(doc))
      doc_without_seats['seats'] = null;
      doc.seats.map( function (seat){
        emit(seat.userID, doc_without_seats);
      });
    }
    

    您确实在发布doc._id而不是doc的正确轨道上。在这种情况下,您构建的索引最大,是大小的1/1000。如果仍需要访问整个文档,则可以在查询时将选项include_docs = true传递给视图。这样就不会将整个文档复制到索引中。

    另一个潜在的优化方法是在seat.userID查找内容时发出您想要引用的内容。如果它仍然很大且难以处理,请使用include_docs方法。