Couchdb 超慢查看,100% cpu 使用率

Couchdb super slow view, 100% cpu usage

账户文档1个。这个文档有大约 1k 个席位。对于每个座位,我们都会发出一个文档。自然地,您会期望这会很慢。地图函数运行如下:

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))
        } 
    }
}

这是在沙发视图地图中遍历文档数组的问题吗?

tldr;

  1. 如果您关心性能,请使用永久视图
  2. doc 在视图中是不可变的。你甚至不能在不复制的情况下添加它。
  3. 发出 _id 并使用 include_docs 几乎总是比发出整个文档作为您的值更好。

说明

这里有几点针对你的问题,使用你的示例文档,其中包含一个名为 seats 的数组,有 1K 个条目。

在这里发布整个文档不是一个好主意。如果这是一个永久视图(如果性能有任何问题,您应该始终使用它),您已经获取了一份文档副本,然后制作了 1000 份副本并按 seat.userID 对它们进行了索引。这效率不高。作为临时视图更糟糕,因为它是在每次调用视图时在内存中动态生成的。

据我所知,该文档在通过视图访问时是完全不可变的,因此您尝试删除席位字段的方式不起作用。因此,删除 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 方法。