Mongodb geonear 和聚合非常慢
Mongodb geonear and aggregate very slow
我当前的 mongo 版本是 2.4.9,collection 有大约 280 万行。在查询中使用 $geonear 时,我的查询需要很长时间才能完成。
我的例子collection
"loc" : {
"type" : "Point",
"coordinates" : [
100.46589473,
5.35149077
]
},
"email" : "abc@123.com"
位置索引
{
"v" : 1,
"key" : {
"loc" : "2dsphere"
},
"ns" : "test.collect",
"name" : "loc_2dsphere",
"background" : true
}
经过测试,此查询大约需要 10 到 15 分钟才能完成
db.getCollection('collect').aggregate(
[
{ '$match':
{'loc':
{'$geoNear':
{'$geometry':
{'type':'Point','coordinates':[101.6862,3.0829],'$maxDistance':10000}
}
}
}
},
{'$group':{'_id':'email', 'email':{'$last':'$email'},'loc':{'$last':'$loc'} }}
])
下面是解释结果
{
"serverPipeline" : [
{
"query" : {
"loc" : {
"$geoNear" : {
"$geometry" : {
"type" : "Point",
"coordinates" : [
101.6862,
3.0829
],
"$maxDistance" : 10000
}
}
}
},
"projection" : {
"email" : 1,
"loc" : 1,
"_id" : 0
},
"cursor" : {
"cursor" : "S2NearCursor",
"isMultiKey" : true,
"n" : 111953,
"nscannedObjects" : 111953,
"nscanned" : 96677867,
"nscannedObjectsAllPlans" : 111953,
"nscannedAllPlans" : 96677867,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 183,
"nChunkSkips" : 0,
"millis" : 895678,
"indexBounds" : {},
"nscanned" : NumberLong(96677867),
"matchTested" : NumberLong(3472481),
"geoMatchTested" : NumberLong(3472481),
"numShells" : NumberLong(53),
"keyGeoSkip" : NumberLong(93205386),
"returnSkip" : NumberLong(20148837),
"btreeDups" : NumberLong(0),
"inAnnulusTested" : NumberLong(3472481),
"allPlans" : [
{
"cursor" : "S2NearCursor",
"n" : 111953,
"nscannedObjects" : 111953,
"nscanned" : 96677867,
"indexBounds" : {}
}
],
"server" : "xxx:xxx"
}
},
{
"$group" : {
"_id" : {
"$const" : "email"
},
"email" : {
"$last" : "$email"
},
"loc" : {
"$last" : "$loc"
}
}
}
],
"ok" : 1
}
我的查询不合适吗,我还能做些什么来提高速度??
尝试直接使用$geoNear聚合管道
https://docs.mongodb.com/v2.4/reference/operator/aggregation/geoNear/
添加到 venkat 的答案(直接在聚合管道中使用 $geoNear
,而不是在 $match
下使用它):
- 如果您不需要所有结果,请尝试减少
$maxDistance
数量。
$geoNear
returns 按距离排序的文档。如果您不需要排序的结果,您可以使用 $geoWithin
代替:https://docs.mongodb.com/v2.4/reference/operator/query/geoWithin/
此外,MongoDB2.4 于 2013 年 3 月发布,不再受支持。如果可能,我会建议您升级到最新版本(当前为 3.2.10)。新版本中有许多错误修复和性能改进。
$geoNear 与聚合框架的工作方式比下面更快(查找查询)
"$near": {
"$geometry": {
"type": "Point",
"coordinates": [lng,lat],
},
},
在某个地方我的 mongodb 也被后者“没有可用的套接字”,但前者工作得很好(<20ms)[也从 golang + mgo 驱动程序测试]
我当前的 mongo 版本是 2.4.9,collection 有大约 280 万行。在查询中使用 $geonear 时,我的查询需要很长时间才能完成。
我的例子collection
"loc" : {
"type" : "Point",
"coordinates" : [
100.46589473,
5.35149077
]
},
"email" : "abc@123.com"
位置索引
{
"v" : 1,
"key" : {
"loc" : "2dsphere"
},
"ns" : "test.collect",
"name" : "loc_2dsphere",
"background" : true
}
经过测试,此查询大约需要 10 到 15 分钟才能完成
db.getCollection('collect').aggregate(
[
{ '$match':
{'loc':
{'$geoNear':
{'$geometry':
{'type':'Point','coordinates':[101.6862,3.0829],'$maxDistance':10000}
}
}
}
},
{'$group':{'_id':'email', 'email':{'$last':'$email'},'loc':{'$last':'$loc'} }}
])
下面是解释结果
{
"serverPipeline" : [
{
"query" : {
"loc" : {
"$geoNear" : {
"$geometry" : {
"type" : "Point",
"coordinates" : [
101.6862,
3.0829
],
"$maxDistance" : 10000
}
}
}
},
"projection" : {
"email" : 1,
"loc" : 1,
"_id" : 0
},
"cursor" : {
"cursor" : "S2NearCursor",
"isMultiKey" : true,
"n" : 111953,
"nscannedObjects" : 111953,
"nscanned" : 96677867,
"nscannedObjectsAllPlans" : 111953,
"nscannedAllPlans" : 96677867,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 183,
"nChunkSkips" : 0,
"millis" : 895678,
"indexBounds" : {},
"nscanned" : NumberLong(96677867),
"matchTested" : NumberLong(3472481),
"geoMatchTested" : NumberLong(3472481),
"numShells" : NumberLong(53),
"keyGeoSkip" : NumberLong(93205386),
"returnSkip" : NumberLong(20148837),
"btreeDups" : NumberLong(0),
"inAnnulusTested" : NumberLong(3472481),
"allPlans" : [
{
"cursor" : "S2NearCursor",
"n" : 111953,
"nscannedObjects" : 111953,
"nscanned" : 96677867,
"indexBounds" : {}
}
],
"server" : "xxx:xxx"
}
},
{
"$group" : {
"_id" : {
"$const" : "email"
},
"email" : {
"$last" : "$email"
},
"loc" : {
"$last" : "$loc"
}
}
}
],
"ok" : 1
}
我的查询不合适吗,我还能做些什么来提高速度??
尝试直接使用$geoNear聚合管道
https://docs.mongodb.com/v2.4/reference/operator/aggregation/geoNear/
添加到 venkat 的答案(直接在聚合管道中使用 $geoNear
,而不是在 $match
下使用它):
- 如果您不需要所有结果,请尝试减少
$maxDistance
数量。 $geoNear
returns 按距离排序的文档。如果您不需要排序的结果,您可以使用$geoWithin
代替:https://docs.mongodb.com/v2.4/reference/operator/query/geoWithin/
此外,MongoDB2.4 于 2013 年 3 月发布,不再受支持。如果可能,我会建议您升级到最新版本(当前为 3.2.10)。新版本中有许多错误修复和性能改进。
$geoNear 与聚合框架的工作方式比下面更快(查找查询)
"$near": {
"$geometry": {
"type": "Point",
"coordinates": [lng,lat],
},
},
在某个地方我的 mongodb 也被后者“没有可用的套接字”,但前者工作得很好(<20ms)[也从 golang + mgo 驱动程序测试]