我正在尝试了解如何最好地使用MongoDB中的索引。让我们说我有一个像这样的文档集合:
{
_id: 1,
keywords: ["gap", "casual", "shorts", "oatmeal"],
age: 21,
brand: "Gap",
color: "Black",
gender: "female",
retailer: "Gap",
style: "Casual Shorts",
student: false,
location: "US",
}
我定期运行查询以查找符合以下每个字段的一组条件的所有文档,例如:
db.items.find({ age: { $gt: 13, $lt: 40 },
brand: { $in: ['Gap', 'Target'] },
retailer: { $in: ['Gap', 'Target'] },
gender: { $in: ['male', 'female'] },
style: { $in: ['Casual Shorts', 'Jeans']},
location: { $in: ['US', 'International'] },
color: { $in: ['Black', 'Green'] },
keywords: { $all: ['gap', 'casual'] }
})
我正在尝试计算我可以创建哪种索引来提高查询速度,例如这样。我应该创建这样的复合索引:
db.items.ensureIndex({ age: 1, brand: 1, retailer: 1, gender: 1, style: 1, location: 1, color: 1, keywords: 1})
或者我可以创建一组更好的索引来优化此查询吗?
答案 0 :(得分:2)
我应该创建这样的复合索引:
db.items.ensureIndex({age:1,品牌:1,零售商:1,性别:1,样式:1,位置:1,颜色:1,关键字:1})
您可以像上面那样创建一个索引,但几乎是整个集合的索引。索引占用空间;索引中的字段越多,使用的空间就越多。通常是RAM,虽然它们可以换掉。他们还会受到处罚。
您的索引似乎很浪费,因为可能仅仅索引其中一些字段会使MongoDB扫描一组接近查找操作预期结果的文档。
我可以创建一组更好的索引来优化此查询吗?
就像我之前说的那样,可能是的。但是这个问题很难在不知道收集细节的情况下回答,比如它有多少文件,每个领域可以有哪些价值,这些价值如何在收集中分配(50%性别男性,50%性别女性?) ,它们如何相互关联等等。
有一些索引策略,但通常您应该努力创建具有高选择性的索引。选择“小”字段组合,这将有助于MongoDB找到扫描“合理”数量的所需文档。同样,“小”和“合理”将取决于您正在执行的集合和查询的特征。
由于这是一个相当复杂的主题,因此这里有一些参考资料可以帮助您构建更合适的索引。
http://emptysqua.re/blog/optimizing-mongodb-compound-indexes/ http://docs.mongodb.org/manual/faq/indexes/#how-do-you-determine-what-fields-to-index http://docs.mongodb.org/manual/tutorial/create-queries-that-ensure-selectivity/
并使用cursor.explain
评估您的索引。
http://docs.mongodb.org/manual/reference/method/cursor.explain/
答案 1 :(得分:0)
像这样的大型索引会在写入时惩罚你。最好只为您需要的索引编制索引,让Mongo的优化程序为您完成大部分工作。如果您的应用程序或数据使用情况发生巨大变化,您可以随时give him an hint或最后重新索引。
您的查询将使用具有一个(快速)的字段的索引,并对其余文档使用表扫描(慢速)。
根据您的应用程序,一些独立的索引可能会更好。添加更多索引不会提高性能。凭借写作能力,它甚至可能使情况变得更糟(YMMV)。
以下是选择要放入索引的字段的基本算法:
答案 2 :(得分:0)
对于您的查询,此索引似乎非常合理。 MongoDB将查询调用为此索引的覆盖查询,因为不需要访问文档。可以从索引中获取所有数据。
来自the docs:
“因为索引”覆盖“了查询,所以MongoDB可以匹配查询条件并仅使用索引返回结果; MongoDB不需要查看文档,只需查看索引即可完成查询。还可以覆盖未加密集合上的聚合管道操作。“
一些评论:
此索引仅供包含年龄过滤器的查询使用。仅按品牌或零售商过滤的查询可能不会使用此索引。
仅在查询的一个或两个最具选择性的字段上添加索引,这将带来非常显着的性能提升。您添加的字段越多,索引大小就越大。
您可能希望生成一些随机样本数据,并使用不同的索引或索引集来衡量其性能。这显然是最安全的了解方式。