【问题标题】:MongoDB not using multikey indexMongoDB不使用多键索引
【发布时间】:2015-08-08 18:39:44
【问题描述】:

我有一个 MongoDB 版本 3.0.3 集合,其中包含具有 2 个字段的文档:

  • 数字长 id
  • 由 60 个数字双精度组成的数组。

我在数组上建立了一个多键索引,并使用getIndexInfo()方法确认索引存在并且是多键。但是,当我查询数组中 2 个特定字段范围的交集时,尽管集合中有 1,000,000 个文档,但 Mongo 不使用此索引。我可以从explain() 方法的输出中看到这一点。更奇怪的是,当我指定使用带有 hint 的索引时,Mongo 会遍历所有 1,000,000 个文档和 60,000,000 个索引条目,我在 explain() 的输出中看到了这些条目。

我正在使用以下代码构建查询:

BasicDBObject q2 = new BasicDBObject("array.0",new BasicDBObject("$lt",1000.0));
BasicDBObject q1 = new BasicDBObject("array.1",new BasicDBObject("$gte",800.0));
BasicDBObject q_and = new BasicDBObject("$and",Arrays.asList(q1,q2));
dbo = collection.find(q_and).explain();

有什么想法吗?

提前感谢您的帮助。

回复解释输出的请求:

不指定提示,解释输出如下:

{ "queryPlanner" : 
{ "plannerVersion" : 1 , "namespace" : "local.TestArrays" , "indexFilterSet" : false , "parsedQuery" : 
{ "$and" : [ 
{ "array.0" : 
{ "$lt" : 1000.0
}
} , 
{ "array.1" : 
{ "$gte" : 800.0
}
}]
} , "winningPlan" : 
{ "stage" : "COLLSCAN" , "filter" : 
{ "$and" : [ 
{ "array.0" : 
{ "$lt" : 1000.0
}
} , 
{ "array.1" : 
{ "$gte" : 800.0
}
}]
} , "direction" : "forward"
} , "rejectedPlans" : [ ]
} , "executionStats" : 
{ "executionSuccess" : true , "nReturned" : 2 , "executionTimeMillis" : 2248 , "totalKeysExamined" : 0 , "totalDocsExamined" : 1000000 , "executionStages" : 
{ "stage" : "COLLSCAN" , "filter" : 
{ "$and" : [ 
{ "array.0" : 
{ "$lt" : 1000.0
}
} , 
{ "array.1" : 
{ "$gte" : 800.0
}
}]
} , "nReturned" : 2 , "executionTimeMillisEstimate" : 2190 , "works" : 1000002 , "advanced" : 2 , "needTime" : 999999 , "needFetch" : 0 , "saveState" : 7812 , "restoreState" : 7812 , "isEOF" : 1 , "invalidates" : 0 , "direction" : "forward" , "docsExamined" : 1000000
} , "allPlansExecution" : [ ]
} , "serverInfo" : 
{ "host" : "NYDEVWS0005052" , "port" : 27017 , "version" : "3.0.3" , "gitVersion" : "b40106b36eecd1b4407eb1ad1af6bc60593c6105"
}
}

当指定要与以下代码一起使用的索引时:

collection.find(q_and).hint("array_1").explain();

解释输出如下:

{ "queryPlanner" : 
{ "plannerVersion" : 1 , "namespace" : "local.TestArrays" , "indexFilterSet" : false , "parsedQuery" : 
{ "$and" : [ 
{ "array.0" : 
{ "$lt" : 1000.0
}
} , 
{ "array.1" : 
{ "$gte" : 800.0
}
}]
} , "winningPlan" : 
{ "stage" : "KEEP_MUTATIONS" , "inputStage" : 
{ "stage" : "FETCH" , "filter" : 
{ "$and" : [ 
{ "array.0" : 
{ "$lt" : 1000.0
}
} , 
{ "array.1" : 
{ "$gte" : 800.0
}
}]
} , "inputStage" : 
{ "stage" : "IXSCAN" , "keyPattern" : 
{ "array" : 1
} , "indexName" : "array_1" , "isMultiKey" : true , "direction" : "forward" , "indexBounds" : 
{ "array" : [ "[MinKey, MaxKey]"]
}
}
}
} , "rejectedPlans" : [ ]
} , "executionStats" : 
{ "executionSuccess" : true , "nReturned" : 2 , "executionTimeMillis" : 61401 , "totalKeysExamined" : 60000000 , "totalDocsExamined" : 1000000 , "executionStages" : 
{ "stage" : "KEEP_MUTATIONS" , "nReturned" : 2 , "executionTimeMillisEstimate" : 56570 , "works" : 60001744 , "advanced" : 2 , "needTime" : 59999998 , "needFetch" : 1743 , "saveState" : 470130 , "restoreState" : 470130 , "isEOF" : 1 , "invalidates" : 0 , "inputStage" : 
{ "stage" : "FETCH" , "filter" : 
{ "$and" : [ 
{ "array.0" : 
{ "$lt" : 1000.0
}
} , 
{ "array.1" : 
{ "$gte" : 800.0
}
}]
} , "nReturned" : 2 , "executionTimeMillisEstimate" : 55620 , "works" : 60001744 , "advanced" : 2 , "needTime" : 59999998 , "needFetch" : 1743 , "saveState" : 470130 , "restoreState" : 470130 , "isEOF" : 1 , "invalidates" : 0 , "docsExamined" : 1000000 , "alreadyHasObj" : 0 , "inputStage" : 
{ "stage" : "IXSCAN" , "nReturned" : 1000000 , "executionTimeMillisEstimate" : 50820 , "works" : 60000000 , "advanced" : 1000000 , "needTime" : 59000000 , "needFetch" : 0 , "saveState" : 470130 , "restoreState" : 470130 , "isEOF" : 1 , "invalidates" : 0 , "keyPattern" : 
{ "array" : 1
} , "indexName" : "array_1" , "isMultiKey" : true , "direction" : "forward" , "indexBounds" : 
{ "array" : [ "[MinKey, MaxKey]"]
} , "keysExamined" : 60000000 , "dupsTested" : 60000000 , "dupsDropped" : 59000000 , "seenInvalidated" : 0 , "matchTested" : 0
}
}
} , "allPlansExecution" : [ ]
} , "serverInfo" : 
{ "host" : "NYDEVWS0005052" , "port" : 27017 , "version" : "3.0.3" , "gitVersion" : "b40106b36eecd1b4407eb1ad1af6bc60593c6105"
}
}

【问题讨论】:

  • 如何使用hint 和java 驱动程序?您还可以在 mongo-shell 中运行相同的查询并发布explain() 的输出吗?
  • 这是我不指定提示时的解释输出:
  • 请将其包含在帖子中

标签: java mongodb indexing multikey


【解决方案1】:

我误解了多键索引的含义。我认为为数组中的每个位置创建了一个单独的索引。但是,在进一步阅读后,我看到为数组创建了一个单一索引,并且文档的所有条目都输入到该单一索引中,而不是保留数组位置。我接受了 n9code 的建议,并在每个字段上创建了单独的字段和索引。这按预期工作。

【讨论】:

    【解决方案2】:

    恐怕您的问题是您正在查询数组的特定元素。因此,即使您在该数组上有索引,查询也必须显式扫描整个集合,从 array 中获取元素 01 并执行匹配。

    如果您需要在特定元素上精确运行匹配,值得将它们从数组中拉出并将它们作为单独的字段,然后在它们上创建索引。所以考虑一下:

    {
       ...
       array: [...],
       ex_element_0: "value0",
       ex_element_1: "value0",
       ...
    }
    

    【讨论】:

      猜你喜欢
      • 2011-11-15
      • 1970-01-01
      • 2014-02-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-07
      • 1970-01-01
      相关资源
      最近更新 更多