2

我正在使用大约 500 平方公里的多边形运行 geoWithin 查询,执行时间很长,大约在 30 秒到 5 分钟之间。集合只有 180k 行,多边形可以从 2km² 到 10,000km² 不等。服务器有大约 4GB 的 RAM。在本地运行(以消除网络延迟)没有明显效果。

我在集合上设置了一个 2dsphere 索引,并将字段数限制为仅返回 _id(目前)。

这是我的文件的样子:

{
  "_id" : ObjectId("..."),
  "geometry" : {
    "type" : "MultiPolygon",
    "coordinates" : [[...]]
  },
  "area_sq_m" : 6699.1309787227955894
}

这是我的索引:

[
    {
        "v" : 1,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_",
        "ns" : "db.output_areas"
    },
    {
        "v" : 1,
        "key" : {
            "geometry" : "2dsphere"
        },
        "name" : "geometry_2dsphere",
        "ns" : "db.output_areas",
        "2dsphereIndexVersion" : 2
    }
]

这是我的查询:

{
    "geometry": {
        $geoWithin: {
            $geometry: {
                type: 'Polygon',
                coordinates: [[ [lng,lat], [lng,lat], [lng,lat] ...]]
            }
        }
    }
}

这是运行的输出explain()

{
  "queryPlanner" : {
    "plannerVersion" : 1,
    "namespace" : "db.output_areas",
    "indexFilterSet" : false,
    "parsedQuery" : {
      "geometry" : {
        "$geoWithin" : {
          "$geometry" : {
            "type" : "Polygon",
            "coordinates" : [...]
          }
        }
      }
    },
    "winningPlan" : {
      "stage" : "PROJECTION",
      "transformBy" : {
        "_id" : 1
      },
      "inputStage" : {
        "stage" : "KEEP_MUTATIONS",
        "inputStage" : {
          "stage" : "FETCH",
          "filter" : {
            "geometry" : {
              "$geoWithin" : {
                "$geometry" : {
                  "type" : "Polygon",
                  "coordinates" : [...]
                }
              }
            }
          },
          "inputStage" : {
            "stage" : "IXSCAN",
            "keyPattern" : {
              "geometry" : "2dsphere"
            },
            "indexName" : "geometry_2dsphere",
            "isMultiKey" : true,
            "direction" : "forward",
            "indexBounds" : {
              "geometry" : [
                "[\"2f0332301\", \"2f0332301\"]",
                "[\"2f03323011\", \"2f03323011\"]",
                "[\"2f033230111\", \"2f033230112\")",
                "[\"2f033230112\", \"2f033230112\"]",
                "[\"2f0332301120\", \"2f0332301121\")",
                "[\"2f0332301121\", \"2f0332301121\"]",
                "[\"2f03323011210\", \"2f03323011211\")",
                "[\"2f03323011211\", \"2f03323011212\")",
                "[\"2f1003230\", \"2f1003230\"]",
                "[\"2f10032300\", \"2f10032300\"]",
                "[\"2f100323000\", \"2f100323001\")"
              ]
            }
          }
        }
      }
    },
    "rejectedPlans" : [ ]
  },
  "serverInfo" : {
    "version" : "3.0.4"
  },
  "ok" : 1
}

这表明正在使用索引。如果我尝试使用较小的区域,则查询确实会变得更快,而使用更大的区域则更慢。

这是我的收藏统计:

{
    "ns" : "db.output_areas",
    "count" : 181408,
    "size" : 3062445568,
    "avgObjSize" : 16881,
    "numExtents" : 22,
    "storageSize" : 3927183360,
    "lastExtentSize" : 1021497344,
    "paddingFactor" : 1,
    "paddingFactorNote" : "paddingFactor is unused and unmaintained in 3.0. It remains hard coded to 1.0 for compatibility only.",
    "userFlags" : 1,
    "capped" : false,
    "nindexes" : 2,
    "totalIndexSize" : 35606480,
    "indexSizes" : {
        "_id_" : 5894896,
        "geometry_2dsphere" : 29711584
    },
    "ok" : 1
}

我运行了db.setProfilingLevel(2)命令,重新运行了查询,然后检查了db.system.profile集合。

第一条记录是实际查询 ( "op": "query")

然后还有 7 个带有 ( "op": "getmore") 的查询,我假设它们正在获取其余数据。

每个查询产生 1000 行 ( "nreturned": 1000),每个查询平均有 4000行millis

我读过很多问题,人们抱怨 geojson 查询占用 > 2s 和 > 1m 行,所以我显然遗漏了一些简单的东西。

4

1 回答 1

0

也许,这不是一个真正的答案,但这可能会解决问题。删除索引并重试,与拥有索引时的执行时间相比,小多边形的查询会较慢,但较大的多边形会更快。

于 2021-01-12T18:58:53.453 回答