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

时间:2017-12-19 19:03:57

标签: mongodb performance indexing mongodb-query

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

假设我们有一个 people 文档集合,其形式如下:

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

让我们假设有一个用于查询集合的web api,并且唯一可能的过滤器是 name age 。 对api的示例调用类似于:http://myAwesomeWebSite/people?name="Bob"&age=25

此类通话将在以下查询中翻译:{{1​​}}。

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

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

尽管如此,我们必须决定以下哪个索引提供最佳性能:

  • 一个复合索引:db.people.find({name: "Bob", age: 25})
  • 两个单字段索引:{name: 1, age: 1}{name: 1}

根据一些简单的测试,似乎单一复合指数比两个单场指数更高效。

通过mongo shell执行单个查询,explain()方法建议使用单个复合索引,您可以比使用两个单字段索引快10倍地查询数据库。

在更现实的情况下,这种差异似乎不那么剧烈,而不是通过mongo shell执行单个查询,而是对nodejs web应用程序的两个不同URL进行多次调用。两个URL都对数据库执行查询,并将获取的数据作为json数组返回,一个使用具有单个复合索引的集合,另一个使用具有两个单字段索引的集合(两个集合具有完全相同的文档)。登记/> 在这个测试中,单一复合指数似乎仍然是性能方面的最佳选择,但这次差异不太明显。

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

有没有人有关于这个主题的经验?我们是否缺少任何重要的考虑因素(可能是大型复合指数的一些缺点)?

1 个答案:

答案 0 :(得分:24)

给定一个简单的标准查询(没有limit()sort()或任何花哨的应用),在两个字段上都有过滤条件(如nameage中所示你的例子),为了找到结果文件,MongoDB将:

  1. 做一个完整的集合扫描(读取整个集合中的每个文档,解析BSON,找到有问题的值,根据输入测试它们并返回/丢弃每个文档):这是超级的I / O激烈,因此很慢。
  2. 使用包含其中一个字段的一个索引(使用索引树查找相关的文档子集,然后扫描它们):具体取决于您的数据分布/索引selectivity可以非常快或几乎不提供任何好处(想象一下30到40年之间数百万人的数据集中的age上的索引 - >每次查找仍然会产生无数的文档。
  3. 使用两个索引,它们一起包含两个有问题的字段(加载两个索引,执行密钥查找,然后计算结果的intersection):同样,根据您的数据分布,这可能会也可能不会给你很好的表现。但是,在大多数情况下,它应该比#2快。但是,如果它比#4快10倍(如你所提到的那样),我会感到惊讶。
  4. 使用 compound index (两个后续的密钥查找会立即导致所需的文档):这将是所有最快的选择,因为它需要最少和最便宜的操作才能到达正确的文件。为了确保最大程度的重用(而不是不受此影响的性能),您通常应首先从最具选择性的字段开始,因此在您的情况下可能name而不是age因为与age相比,很多人会有name(选择性低)(选择性更高)。但是,该选择还取决于您的具体方案以及您打算针对数据库运行的查询。网上有一篇非常好的文章,关于如何最好地定义考虑到您特定情况的各个方面的复合索引:https://emptysqua.re/blog/optimizing-mongodb-compound-indexes
  5. 需要考虑的其他方面是:索引更新以特定价格出现。但是,如果您只关心原始读取速度并且每次只进行一些更新,那么您应该选择更多/更大的索引。

    最后但并非最不重要的(!)过度使用的底线建议:使用真实数据甚至是真实的负载情景来描述你的系统。并随着数据/系统的变化而不断进行测量。

    补充读物: 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

    Index intersection vs. compound index?

    mongodb compund index vs. index intersect

    How does the order of compound indexes matter in MongoDB performance-wise?

    In MongoDB, I am using a large query, how I will create compound index or single index, So My response time boost up