【问题标题】:MongoDB Optimizing FindAndModify or Find + SortMongoDB 优化 FindAndModify 或 Find + Sort
【发布时间】:2012-08-20 10:40:00
【问题描述】:

运行 MongoDB,我正在尝试将具有优先级 (d) 的三列键查找 (a,b,c) 排队。我有一个类似(pymongo 语法)的查询:

collection.find({'a':'foo','b':'bar','c':'baz'}, sort = [('d', -1)] )

使用复合索引 (a+1,b+1,c+1,d-1) 运行解释显示全表扫描和 BasicCursor。

对于 d 上的单个索引,explain 显示仅使用 d 索引。

对于一个大表,我真正想要的是使用复合索引。我怎样才能做到这一点?

索引信息: {u'id': {u'key': [(u'_id', 1)], u'v': 1}, u'color_1_level_1_in_progress_1_Ranking_-1': {u'key': [(u'color', 1), (u'level', 1), (u'in_progress', 1), (u'排名', -1)], u'v': 1}}

EXPLAIN ON A FIND+SORT QUERY
db.coll.find({'level' : {'$in' : [0,1,2]}, 'in_progress' : 0, 'color' : {'$in' : ['Red', 'Blue', 'Green]} },  sort = [('Ranking', -1)] ).explain()

OUTPUT ON EXPLAIN
OperationFailure: database error: too much data for sort() with no index.  add an index or specify a smaller limit


THE QUEUEING QUERY I CARE ABOUT OPTIMIZING
coll.find_and_modify(
  query = {'level' : {'$in' : [0,1,2]}, 'in_progress' : 0, 'color' : {'$in' : ['Red', 'Blue', 'Green']} },
  sort = {'Ranking' : -1},                                                                                                                                                                             
  update = {'$set': {'in_progress': 1}} 
)   

请注意,当我在排序字段“排名”上添加索引时,解释返回正在使用排名索引。但是从不使用复合索引,并且在 1.5 MM 的文档测试语料库上性能非常慢。

【问题讨论】:

  • 能否发布 db.collection.getIndexes()、查询和 explain() 的输出?
  • 是的,但我需要一些时间。明天早上应该起床。
  • 我应该跟进,在更改查询规范以不使用逻辑 '$in' 或其他运算符并简单地查询特定值之后,mongo 想出使用索引。但!它似乎没有使用索引进行排序操作,而是更愿意扫描与查询匹配的所有文档。奇怪!
  • 我遇到了同样的问题...如果我找到任何东西,我会告诉你
  • 我认为 $in 相当于对 $in 数组中的每个元素执行单独的查询。如果您使用两个 $in 运算符,每个运算符有 3 个元素,则相当于 3*3 = 9 个单独的索引查询。我可能会看到查询优化器如何决定表扫描更快。

标签: python mongodb pymongo database


【解决方案1】:

有一种方法可以在查询时强制使用特定的索引,称为hint

只需在光标上调用它:

cursor = collection.find({query-doc}).hint({index-fields})

【讨论】:

    【解决方案2】:

    Mongodb 索引系统是基于实验的。基本上,查询优化器将使用所有可能的索引运行您的查询并比较每个索引的时间。它将学习为给定类型的查询使用最佳索引。 来自query optimizer 上的文档:

    在测试新计划时,MongoDB 会并行执行多个查询计划。一旦一个完成,它就会终止其他的执行,并且系统已经知道哪个计划是好的

    如果您的集合非常小,则查询优化器选择的索引可能不是您认为最好的。但是,此查询和此集合的速度更快。 当您的收藏长大后,也许另一个索引会更合适。

    在您的情况下,我认为 mongo 更容易扫描所有文档,然后使用 d 上的索引对它们进行排序,因为您的文档很少。

    尝试对包含更多文档(比如说 100 万个)的集合运行相同的查询(多次以提高学习效率),您可能会看到它将使用完整索引。

    因此,没有必要使用 oe 提示(虽然它不会有害)。我的建议:让 mongo 查询优化器完成它的工作 :-)

    【讨论】:

    • 感谢您深入了解 mongo 如何在幕后确定查询计划。不幸的是,我的测试语料库有超过 1.5 个 MM 文档,并且查询仍在运行全表扫描。我知道我可以通过限制结果集或仅针对查询规范中的一系列排名值来更粗略地优化 find() 操作。但是,这并不能真正帮助我优化 findAndModify 查询,因为此操作需要原子地锁定记录。
    猜你喜欢
    • 2016-03-31
    • 2017-03-11
    • 1970-01-01
    • 2017-03-19
    • 2017-01-10
    • 1970-01-01
    • 1970-01-01
    • 2014-08-30
    • 2015-11-18
    相关资源
    最近更新 更多