1

我有几个 CouchDB 数据库。最大的是大约 600k 个文档,我发现查询时间过长(几个小时或更长时间)。数据库不经常更新(大约一个月一次),只涉及添加新文档,从不更新现有文档。

查询的类型:查找所有文档,其中key1='a'或多个键: key1='a', key2='b'...

我认为永久视图在这里并不实用,因此一直在使用 CouchDB-Python 的“查询”方法。

我尝试了几种方法,但我不确定哪种方法最有效,或者为什么。

方法一:map函数为:

    map_fun = '''function(doc){
        if(doc.key1=='a'){
            emit(doc.A, [doc.B, doc.C,doc.D,doc.E]);
        }
    }'''

Python 查询是: results = ui.db.query(map_fun, key2=user)

然后对 results.rows 进行一些操作。这占用了最多的时间。

'results.rows' 需要大约一个小时才能返回。如果我将 key2 更改为其他内容,它会在大约 5 秒内返回。如果我重复原始用户,它也很快。

但有时我需要查询更多的键,所以我尝试:

    map_fun = '''function(doc){
        if(doc.key1=='a' && doc.key2=user && doc.key3='something else' && etc.){
            emit(doc.A, [doc.B, doc.C,doc.D,doc.E]);
        }
    }'''

并使用 python 查询:

results = ui.db.query(map_fun) 然后对 results.rows 进行一些操作

第一次查询需要很长时间。当我更改 key2 时,又需要很长时间。如果我将 key2 更改回原始数据,则需要相同的时间。(也就是说,似乎没有任何东西被缓存,B-tree'ed 或其他)。

所以我的问题是:在 couchdb-python 中进行查询的最有效方法是什么,其中查询是临时的并且涉及搜索条件的多个键?

UI 是基于 QT 的,在下面使用 PyQt。

4

2 回答 2

3

couchdb-python db.query()方法有两个注意事项:

  1. 它执行临时视图。这意味着代码流处理将被阻止,直到所有文档都由该视图处理。每次通话都会一次又一次地发生这种情况。尝试保存视图并使用db.view()方法来按需获取结果并进行增量索引更新。

  2. 无论它有多大,它都会读取整个结果。db.query() 和 db.view() 方法都不是惰性的,所以如果视图结果是 100 MB JSON 对象,您必须在以某种方式使用它们之前获取所有这些数据。要以更优化内存的方式查询数据,请尝试将补丁应用到具有db.iterview()方法 - 它允许您以分页样式获取数据。

于 2012-08-22T20:22:58.633 回答
1

我认为解决您的问题的方法是为您正在搜索的键创建索引。这就是你所说的常见。

请注意基于 B 树的表中的 map/reduce 和 SQL 查询之间的区别:

  • 搜索键(如果有索引)的简单 SQL 查询遍历 B+-树中从根到叶的单个路径,
  • map 函数读取所有元素,如果它发出小结果,则事件。

您正在做的是针对每个查询

  1. 阅读每份文件(大部分费用)和
  2. 在发出的结果中搜索一个键(在 B 树中快速搜索)。

而且我认为您的解决方案在设计上必须很慢。

如果您重新设计数据库结构以使永久视图实用,则 (1.) 将执行一次,并且对于每个查询仅执行 (2.)。添加到数据库后,视图将读取每个文档,并且查询将在存储发出结果的 B-tree 中搜索。如果发出的集合小于总文档数,则查询搜索较小的结构,您将比 SQL 数据库受益。

临时视图的效率远低于永久视图,并且仅用于开发。CouchDB 旨在使用永久视图。为了使 map/reduce 高效,必须实现缓存或使视图永久化。我不熟悉 CouchDB 实现的细节,也许由于一些缓存,使用不同键的第二个查询更快。如果由于某种原因您必须使用临时视图,那么 CouchDB 可能是一个错误,您应该考虑为 MongoDB 等在线查询创建和优化 DBMS。

于 2012-08-24T08:25:10.640 回答