【发布时间】:2015-10-31 05:25:36
【问题描述】:
鉴于集合 locations 包含约 20,000,000 个具有 3 个属性的文档:
{
_id,
name, // string
geo // coordinate pair, e.g. [-90.123456, 30.123456]
}
还有一个name: 1 的索引和一个像这样的地理索引设置:
{
"geo" : "2dsphere"
},
{
"v" : 1,
"name" : "geo_2dsphere",
"ns" : "db.locations",
"min" : "-180.0",
"max" : "180.0",
"w" : 1.0,
"2dsphereIndexVersion" : 2
}
如何在geo_2dsphere 索引和name 索引上针对此集合进行高效查询?
当我仅对地理索引运行 $box 查询时,需要 20 多秒才能返回 50 个结果。当我对 name 属性进行搜索时,它会进一步上升。
如果我运行$near 查询,那么事情可以 执行得非常快,但有时查询似乎(非常随机地)从大约 200 毫秒到几秒。请参阅此示例,其中唯一的区别是名称索引上的一个附加字符实际上会增加时间:
200 毫秒:
{name: /^mac/, geo: {$near: {$geometry: {type: "Point", coordinates: [ -90.123456, 30.123456 ]}, $maxDistance: 20000}}}
18,000 毫秒:
{name: /^macy/, geo: {$near: {$geometry: {type: "Point", coordinates: [ -90.123456, 30.123456 ]}, $maxDistance: 20000}}}
我不明白为什么更具体的索引会大大减慢速度。当我更具体地使用某个短语时,我必须将$maxDistance 大幅减少到大约 7,000 米,然后查询才能在任何合理的时间内返回。
我应该在这里做更好的设置吗?
【问题讨论】:
-
你不能。查询评估中有一个“higlander 规则”(只能有一个),它拒绝在查询评估中使用多个“一个”“特殊”索引。因此,您不能在
$or条件下使用多个“文本”或多个“地理空间”或“文本”和“地理空间”的任何组合或使用任何其他内容,这会导致多个索引选择。至于您的查询时间变化。 “太宽泛”。您需要正确采样,这意味着在没有其他操作且在内存中“完全加热”(所有可能的结果)的干净主机上。 -
谢谢布雷克斯。我意识到我的时间示例太宽泛了,我并不是要具体考虑它们,只是响应时间显然存在不希望的和多变的差异。我想我们需要完全研究一个不同的数据库。
-
这里还有一个变体“catch”,其中“搜索名称”的概念很可能不是缩小该数据的范围。例如:
.createIndex({ "name": 1, "geo": "2dphere" })原则上看起来不错。但是,如果“macy”比“geo”点附近的位置“更多”,那么这将适得其反。索引是“数据感知”的设计,而不仅仅是您用来查询的术语。多年来,Propellerheads 在 SQL 社区中一直在吹嘘这一点。主要原因是没有其他人完全理解索引概念。
标签: mongodb geospatial