提问者:小点点

MongoDB查找性能:单个复合索引VS两个单个字段索引


我正在寻找有关在MongoDb 3.4中使用哪种索引策略的建议。

假设我们有一个具有以下形状的人员文档集合:

{
    _id: 10,
    name: "Bob",
    age: 32,
    profession: "Hacker"
}

让我们想象一个用于查询集合的Web api被公开,唯一可能的过滤器是按名称或年龄。
对api的示例调用将类似于:超文本传输协议://myAwesomeWebSite/people? name="Bob"

这样的调用将在以下查询中翻译:db. People.find({name:"Bob",age:25})

为了更好地阐明我们的场景,请考虑:

  • 字段名称已经在我们的文档中,并且我们已经在该字段上有一个索引
  • 由于我们应用程序的一些新功能,我们将添加新的字段age
  • 数据库只能通过上面提到的web api访问,最重要的要求是公开一个超快速的web api
  • 对web api的所有调用都将对字段name和age应用过滤器(换句话说,对web api的所有调用都将具有相同的模式,即上面显示的模式)

也就是说,我们必须决定以下哪个索引提供最佳性能:

  • 一个复合索引:{name: 1,age:1}
  • 两个单字段索引:{name: 1}{age:1}

根据一些简单的测试,单个复合索引似乎比两个单字段索引更具性能。

通过通过mongoshell执行单个查询,解释()方法建议使用单个复合索引可以比使用两个单个字段索引快近十倍地查询数据库。

在更现实的场景中,这种差异似乎不那么引人注目,在这种场景中,不是通过mongoshell执行单个查询,而是对nodejs Web应用程序的两个不同url进行多次调用。两个url都执行对数据库的查询,并将获取的数据作为json数组返回,一个使用具有单个复合索引的集合,另一个使用具有两个单字段索引的集合(两个集合具有完全相同的文档)。
在这个测试中,单个复合索引似乎仍然是性能方面的最佳选择,但这次差异不那么明显。

根据测试结果,我们正在考虑使用单复合指数方法。

有人对这个主题有经验吗?我们是否错过了任何重要的考虑因素(也许是大复合索引的一些缺点)?


共1个答案

匿名用户

给定一个普通的标准查询(没有limited()sort()或任何花哨的应用程序),它在两个字段上有过滤条件(如示例中的nameage),为了查找生成的文档,MongoDB将:

  1. 进行完整的集合扫描(读取整个集合中的每个文档,解析BSON,找到有问题的值,根据输入测试它们并返回/丢弃每个文档):这是超级I/O强度,因此很慢。
  2. 使用一个包含其中一个字段的索引(使用索引树定位文档的相关子集,然后扫描它们):根据您的数据分布/索引选择性,这可能非常快或几乎没有任何好处(想象一下在数百万30到40岁之间的数据集中的age索引-

其他需要考虑的方面是:索引更新有一定的代价。但是,如果您只关心原始读取速度,并且偶尔只有一些更新,那么您应该选择更多/更大的索引。

最后但同样重要的是(!)被过度使用的底线建议:使用真实数据甚至现实的负载场景来分析您的系统。并随着数据/系统随时间的变化而不断测量。

补充案文:https://docs.mongodb.com/manual/core/query-optimization/index.html

https://dba.stackexchange.com/questions/158240/mongodb-index-intersection-does-not-eliminate-the-need-for-creating-compound-in

指数交集vs.复合指数?

mongoDB组合索引与索引相交

在MongoDB性能方面,复合索引的顺序如何重要?

在MongoDB中,我使用的是大型查询,我将如何创建复合索引或单索引,因此我的响应时间提升了