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

Ell*_*iot 2 couchdb

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

function(doc) {
    if (doc.type == 'account') {
        doc.seats.map(function(seat) {
            emit(seat.userID, doc))
        } 
    }
}
Run Code Online (Sandbox Code Playgroud)

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

function(doc) {
    if (doc.type == 'account') {
        doc.seats.map(function(seat) {
            delete doc.seats
            emit(seat.userID, doc))
        } 
    }
}
Run Code Online (Sandbox Code Playgroud)

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

function(doc) {
    if (doc.type == 'account') {
        doc.seats.map(function(seat) {
            emit(seat.userID, doc.id))
        } 
    }
}
Run Code Online (Sandbox Code Playgroud)

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

sar*_*war 5

tldr;

  1. 如果您关心性能,请使用永久视图
  2. doc从视图中是不可变的.如果不制作副本,您甚至无法添加.
  3. 发出_id并使用include_docs几乎总是比发出整个doc作为你的值更好.

说明

以下是您的问题的几点,使用您的示例文档,其中包含一个名为seat的阵列,其中包含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);
  });
}
Run Code Online (Sandbox Code Playgroud)

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

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