如何使用$nin、$in等运算符提高Mongodb的查询性能
我有一个相当大的数据集,包含超过300万个文档,这些文档具有类似StackOverflow的标记,每个问题都使用标记。我用于存储标记的模式如下所示:如何使用$nin、$in等运算符提高Mongodb的查询性能,mongodb,tagging,Mongodb,Tagging,我有一个相当大的数据集,包含超过300万个文档,这些文档具有类似StackOverflow的标记,每个问题都使用标记。我用于存储标记的模式如下所示: {"id": 12345, "tags":["tag1", "tag2", "tag3"]}, {"id": 12346, "tags":["tag2", "tag3"]} 我在标记字段上创建了一个多键索引。当我使用$in或$nin运算符执行查询以查找标记的交集、并集时,在服务器类机器上的性能大约为7秒。我能做些什么来提高查询搜索的速度吗 编辑1
{"id": 12345, "tags":["tag1", "tag2", "tag3"]}, {"id": 12346, "tags":["tag2", "tag3"]}
我在标记字段上创建了一个多键索引。当我使用$in或$nin运算符执行查询以查找标记的交集、并集时,在服务器类机器上的性能大约为7秒。我能做些什么来提高查询搜索的速度吗
编辑1:
这是我们要求的解释计划。我观察到,在我重新启动服务器并只运行mongodb服务器之后,查询返回的速度要快得多。查询执行得更快(<50ms)。我怀疑索引没有缓存在内存中,尽管我有足够的未使用ram可用,并且我的索引(800MB)可以很容易地放入内存中
find({“tags”){$in:['tag1','tag2'],$nin:['tag4','
tag5','tag6','tag7']});
{
“游标”:“BtreeCursor标记\u 1 multi”,
“未扫描”:6145193,
“nscannedObjects”:6145192,
“n”:969386,
“米利斯”:19640,
“NYELDS”:0,
“跳过”:0,
“isMultiKey”:没错,
“indexOnly”:错误,
“指数边界”:{
“标签”:[
[
“tag1”,
“tag1”
],
[
“tag2”,
“tag2”
]
]
}
}
注意使用
db.col.stats()
检查多键标记索引的大小。如果它不适合RAM,那么您可能会被磁盘绑定,并导致一些磁盘IO成本。如果索引完全放在内存中,那么除了投入更多的硬件之外,我不确定你还能做什么,除非你能优化查询本身
您是否需要搜索所有数据,或者是否可以查询由另一个索引字段过滤的子集?或者,您可以消除
$nin
查询,因为必须迭代每个标记,而as$in只需迭代,直到找到匹配项。使用db.col.stats()
检查多键标记索引的大小。如果它不适合RAM,那么您可能会被磁盘绑定,并导致一些磁盘IO成本。如果索引完全放在内存中,那么除了投入更多的硬件之外,我不确定你还能做什么,除非你能优化查询本身
您是否需要搜索所有数据,或者是否可以查询由另一个索引字段过滤的子集?或者,您是否可以消除
$nin
查询,因为必须迭代每个标记,而as$in只需迭代直到找到匹配项,因此查询速度往往会较慢。这就是我认为的优化(尽管您可能需要对其进行测试)
不确定性能提升的数量,但仍值得尝试与当前实现进行比较。这就是我认为的优化(尽管您可能需要测试它)
不确定性能提升的数量,但仍然值得尝试与您当前的实现进行比较。如果您希望性能超快并且没有空间限制,我建议使用视频id数组单独收集标签,并在标签名称上建立索引 如果您希望性能超快且没有空间限制,我建议使用视频id数组单独收集标签,并在标签名称上建立索引 这里是另一个建议,但我还没有机会测试它
{
tags:{
items:[ 'a', 'b', 'c' ],
mixed:{
a:1, // hash value for a tag
b:2, // hash value for b tag
c:3 // hash value for c tag
}
}
}
搜索查询是
db.demo.find({ 'tags.mixed.a':1, 'tags.mixed.b':2 })
如果可能,我必须为
标签创建复合索引。混合这里是另一个建议,但我还没有机会测试它
{
tags:{
items:[ 'a', 'b', 'c' ],
mixed:{
a:1, // hash value for a tag
b:2, // hash value for b tag
c:3 // hash value for c tag
}
}
}
搜索查询是
db.demo.find({ 'tags.mixed.a':1, 'tags.mixed.b':2 })
如果可能,您必须创建com