【问题标题】:MongoDB large collection slow searchMongoDB大集合慢搜索
【发布时间】:2013-05-13 10:17:39
【问题描述】:

我有大型 mongodb 集合(530 万个条目),每个条目都有列表字段和一些附加字段。例如:

{ "_id" : ObjectId("518d51c808beda0b70cffffa"), 
  "a" : [ 0.00037, 0.00009 ], 
  "b" : "Some long str", 
  "c" : [ "element1", "element2", "element3" ] 
}

我在字段c 上有索引,我想对其进行搜索。此外,我想按此列表的所有排列进行搜索,例如,我希望上面的对象出现在查询 "c": ["element3", "element2", "element1"] 的搜索结果中。

我是这样使用pymongo的:

from itertools import permutations
...
query = ['element1', 'element2', 'element3']
query_permutations = list(permutations(query, len(query)))
results = collection.find({"c": {"$in": query_permutations}}).sort("a", -1)

有什么方法可以让它更快?

UPD:在较小版本的集合上解释():

{
    "cursor" : "BasicCursor",
    "isMultiKey" : false,
    "n" : 11053,
    "nscannedObjects" : 11053,
    "nscanned" : 11053,
    "nscannedObjectsAllPlans" : 11053,
    "nscannedAllPlans" : 11053,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "millis" : 41,
    "indexBounds" : {

    },
    "server" : "machine.local:27017"
}

【问题讨论】:

  • 你能给我们一个explain()吗?集合上的索引是什么?
  • 是的,该查询没有使用索引,您可能想添加 {c:1,a:-1} 或者如果 mongo 优化器会看到它 {a:-1,c:1} 但我不确定优化器是否会看到后一个索引,但它会一个基本排序的 $in range
  • @Sammaye 出现错误cannot index parallel arrays [c] [a]
  • a 是数组类型?编辑:愚蠢的我,我没有看问题顶部的文档结构
  • 我不确定a 上的排序会有多大用处,您希望完成什么?

标签: python mongodb pymongo


【解决方案1】:

Compound multikey indexes may only include one array field。您的字段 a 和 c 都是数组,您不能创建索引 {c:1,a:-1},但可以创建索引{c:1}:

db.collection.ensureIndex({c: 1})

另外,请考虑在查询中使用运算符 $all,这样您就无需在字段 c 上创建元素排列。但是,如果您将 $in 替换为 $all,则查询将返回包含在查询中未指定其他元素的文档的元素:

{ "_id" : ObjectId("518d51c808beda0b70cffffa"),
  "a" : [ 0.00037, 0.00009 ],
  "b" : "Some long str",
  "c" : [ "element1", "element2", "element3", "element4" ]
}

为了防止这种情况,您可以将运算符 $all 与运算符 $size 结合使用:

results = collection.find({"c": {"$all": query, "$size": len(query)}}).sort("a", -1)

编辑:

正如@Sammaye 所说,对于复合索引,您有第三种选择。您可以重新设计架构并将 a 字段分解为更多字段,但您需要问自己 要在此查询中执行哪种类型的排序。

【讨论】:

  • 我认为 $in 是他正在寻找的操作员,我不知道问题的哪一部分让您退出 $all,而且只有 c 上的索引不是最佳的,因为它会创建一个scanandorder案例
  • @Sammaye,创建具有多个数组字段的复合索引是不可能的,所以他有两个选择。他可以使用索引扫描或根本不使用索引。
  • @Sammaye,他想要 to 搜索 by all i> permutations 列表,所以他只是创建一个巨大的查询来使用 $in。
  • 他有第三个选择,模式改变。在这种情况下,这样的改变会比考虑 scanandorder 更好。另外,英语听起来更像是他想按列表中的所有排列扫描文档,这并不意味着文档需要包含“所有”排列
  • 还有一点是他想要如何搜索,对子文档的排序可能无法提供他实际寻找的排序 (a[0] ),即我也不确定您为什么建议对多键字段进行排序是个好主意
猜你喜欢
  • 2015-08-25
  • 1970-01-01
  • 2014-07-31
  • 2021-04-17
  • 1970-01-01
  • 1970-01-01
  • 2013-12-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多