CouchDB Python查询性能



我有几个CouchDB数据库。最大的是大约60万个文档,我发现查询太长了(几个小时或更长)。DB很少更新(大约一个月更新一次),只涉及添加新文档,从不更新现有文档。

查询类型为:查找包含key1='a'或多个关键字的所有文档:key1='a', key2='b'。。。

我认为永久视图在这里不实用,所以一直在使用CouchDBPython的"query"方法。

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

方法1:地图功能是:

    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)然后进行一些带有结果的操作。行

第一个查询需要很长时间。当我更改键2时,又需要很长时间。如果我将key2更改回原始数据,所花费的时间相同。(也就是说,似乎没有任何东西被缓存、B树或其他什么)。

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

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

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

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

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

我认为解决问题的方法是为正在搜索的键创建一个索引。这就是你所说的"永久视野"。

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

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

您所做的是针对每个查询

  1. 阅读每个文档(大部分成本),以及
  2. 在发出的结果中搜索关键字(在B-树中快速搜索)

我认为你的解决方案在设计上一定很慢。

如果您重新设计数据库结构以使永久视图变得实用,则(1.)将执行一次,每个查询只执行(2.)。添加到DB后,每个文档将被视图读取,查询将在存储发出结果的B树中搜索。如果发出的集合小于文档总数,那么查询将搜索更小的结构,并且您可以获得优于SQL数据库的优势。

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

最新更新