我在 MongoDB 中尝试 Atlas Search,发现了一个奇怪的行为。
考虑 100000 个文档的集合,如下所示:
{
_id: "1",
description: "Lorem Ipsum",
creator: "UserA"
}
使用具有以下基本定义的 Atlas 搜索索引:
{
mappings: { dynamic: true }
}
出于示例的目的,Atlas Search 索引是此集合上唯一创建的索引。
现在这里有一些聚合并估计每个聚合的执行时间:
$单独搜索~100ms
[
{
$search: {
wildcard: {
query: "*b*",
path: {
wildcard: "*"
},
allowAnalyzedField: true
}
}
}
]
$search 与简单的 $match 不返回任何内容 ~25 秒(请记住,这只是 100000 个文档,如果我们不必担心网络,此时过滤客户端会更快)
[
{
$search: {
wildcard: {
query: "*b*",
path: {
wildcard: "*"
},
allowAnalyzedField: true
}
}
},
{
$match:{creator:null}
},
{
$limit: 100
}
]
$match 不返回任何结果 ~100ms
[
{
$match:{creator:null}
},
{
$limit: 100
}
]
假设所有文档都与 $search 匹配,则这些 $match 都需要扫描所有文档。
我想也许是因为 $match 是第一阶段,Mongo 可以直接在集合上工作,但不,这个故意未优化的管道工作得很好:
$match 与 $set 强制 $match 直接在管道上工作 ~200ms
[
{
$set:
{
creator: {
$concat: ["$creator", "ABC"]
}
}
},
{
$match: {
creator: null
}
},
{
$limit: 100
}
]
用 $sort 替换 $match 得到类似的结果
我知道 Atlas Search 不鼓励使用 $match 和 $sort 并提供替代方案,但看起来性能应该不会那么糟糕。我有一个非常具体的用例,非常希望能够在 $search 后使用 $match 或 $sort,而 Mongo 提出的替代方案并不完全是我所需要的。
什么可以解释这一点?是Mongo缺乏优化吗?这是一个错误吗?
我确实发现使用 StoredSource 显着提高了性能(~500ms),但我仍然不明白为什么这么想......
编辑:我在另一个数据库中尝试了完全相同的操作,但它仍然很慢,所以我更加困惑......