钥匙要点
在MongoDB中进行索引可以通过减少需要阅读的完整文档的数量来大大提高性能和吞吐量,从而提高应用程序性能。
MongoDB支持几种类型的索引,包括默认_id索引,辅助索引,化合物索引,Multikey Index和Multikey化合物索引。每种类型都有特定的目的,用于不同类型的查询。- >
>可以在集合上定义多个索引,但是查询在执行过程中只能使用一个索引。最好的索引是由MongoDB的Query-Optimizer选择在运行时选择的。- >
>索引可以大大改善阅读操作,但也会造成自身成本。索引操作占据空间,并在收藏集中的每个插入,更新和删除操作上引起额外的开销。因此,索引收益较重的收藏量比写入较重的收藏。
-
索引是与MongoDB合作的最重要概念之一。正确理解至关重要,因为索引可以通过减少要阅读的完整文档的数量来大大提高性能和吞吐量,从而提高应用程序的性能。因为索引很难理解,所以这个两部分系列将仔细研究它们。
在本文中,我们将探讨以下五种索引:
- >默认_id索引
辅助索引
- 复合索引
- 多基索引
- > Multikey Compound Index
-
还有其他一些类型的讨论,但是从逻辑上讲,我将它们保留在第2部分中,以提供清晰的理解并避免任何混乱。
尽管可以在集合上定义多个索引,但是在执行过程中,查询只能使用一个索引。 MongoDB的查询选项器在运行时做出最佳索引的决定。
本文假设您对MongoDB概念(例如集合,文档等)有基本的了解,并使用PHP(例如查找和插入)进行基本查询。如果没有,我建议您阅读我们的初学者文章:重新审视MongoDB和MongoDB的简介。
对于该系列,我们将假设我们有一个名为帖子的帖子,其中填充了500个文档,具有以下结构:
现在,让我们详细探讨各种类型的索引。
- >默认_id索引
默认情况下,MongoDB在每个集合的_id字段上创建一个默认索引。每个文档都有一个唯一的_id字段作为主键,一个12字节的objectid。如果没有其他可用索引,则默认情况下将用于各种查询。
要查看集合的索引,请打开MongoDB外壳并执行以下操作:
<span>{
</span> <span>"_id": <span>ObjectId</span>("5146bb52d852470060001f4"),
</span> <span>"comments": {
</span> <span>"0": "This is the first comment",
</span> <span>"1": "This is the second comment"
</span> <span>},
</span> <span>"post_likes": 40,
</span> <span>"post_tags": {
</span> <span>"0": "MongoDB",
</span> <span>"1": "Tutorial",
</span> <span>"2": "Indexing"
</span> <span>},
</span> <span>"post_text": "Hello Readers!! This is my post text",
</span> <span>"post_type": "private",
</span> <span>"user_name": "Mark Anthony"
</span><span>}</span>
GetIndexes()方法返回我们集合的所有索引。如您所见,我们的默认索引带有名称_id_ 。密钥字段表明索引在_id字段上,1的值表示升序顺序。我们将在下一节中了解订购。
辅助索引
对于要在_id字段以外的字段上使用索引的情况,我们必须定义自定义索引。假设我们要根据user_name字段搜索帖子。在这种情况下,我们将在集合的User_name字段上定义自定义索引。除默认索引外,此类自定义索引称为辅助索引。
为了证明索引对数据库的效果,让我们简要分析查询性能而不先索引。为此,我们将执行查询,以查找所有具有“ Jim Alexandar”的user_name的帖子。
<span>{
</span> <span>"_id": <span>ObjectId</span>("5146bb52d852470060001f4"),
</span> <span>"comments": {
</span> <span>"0": "This is the first comment",
</span> <span>"1": "This is the second comment"
</span> <span>},
</span> <span>"post_likes": 40,
</span> <span>"post_tags": {
</span> <span>"0": "MongoDB",
</span> <span>"1": "Tutorial",
</span> <span>"2": "Indexing"
</span> <span>},
</span> <span>"post_text": "Hello Readers!! This is my post text",
</span> <span>"post_type": "private",
</span> <span>"user_name": "Mark Anthony"
</span><span>}</span>
解释()返回与索引相关的信息。上述解释()的输出如下所示:
值得一看的一些重要键是:
- 光标 - 指示查询中使用的索引。 basiccursor表示使用了默认_id索引,MongoDB必须搜索整个集合。继续,我们会看到,当我们应用索引时,btreecursor将被使用而不是> basiccursor。
n - 指示返回查询的文档数量(在这种情况下为一个文档)。- >
nscannedObjects - 指示查询搜索的文档数量(在这种情况下,搜索了所有500个文档)。如果集合中的文档数量很大,则可以是一个大开销的操作。>
- nscanned - 指示在数据库操作过程中扫描的文档数量。
-
理想情况下,n应等于或接近NScann,这意味着搜索最少数量的文档。
现在,让我们执行相同的查询,但使用辅助索引。要创建索引,请在MongoDB Shell中执行以下操作:
我们在user_name字段上创建了一个索引
在帖子中使用SuereIndex()方法集合。我敢肯定,您已经将订单参数的值置于该方法上,该方法指示搜索的上升(1)或降序(-1)订单。为了更好地理解这一点,请注意每个文档都有一个时间戳字段。如果我们首先想要最新的帖子,我们将使用降序订单。对于最古老的帖子,我们将选择上升订单。
创建索引后,使用相同的find()和divell()方法来像以前一样执行和分析查询。 IS的输出:

输出显示查询使用btreecursor命名user_name_1 (我们之前定义了),并且仅扫描了一个文档,而不是与上一个查询中搜索的500个文档相反,而无需索引。
就目前而言,了解所有MongoDB索引都使用其算法中的BTREE数据结构,而Btreecursor是其默认光标。本文的详细讨论不范围,但这不会影响任何进一步的理解。
以上比较表明索引如何显着改善查询性能。
复合索引
在某些情况下,查询使用多个字段。在这种情况下,我们可以使用复合索引。考虑以下查询,该查询同时使用post_type和post_likes字段:
<span>{
</span> <span>"_id": <span>ObjectId</span>("5146bb52d852470060001f4"),
</span> <span>"comments": {
</span> <span>"0": "This is the first comment",
</span> <span>"1": "This is the second comment"
</span> <span>},
</span> <span>"post_likes": 40,
</span> <span>"post_tags": {
</span> <span>"0": "MongoDB",
</span> <span>"1": "Tutorial",
</span> <span>"2": "Indexing"
</span> <span>},
</span> <span>"post_text": "Hello Readers!! This is my post text",
</span> <span>"post_type": "private",
</span> <span>"user_name": "Mark Anthony"
</span><span>}</span>
用divell()分析此查询,给出以下结果,这表明查询使用基本cursor,所有500个文档都被扫描以检索一个文档。
这是高效的,所以让我们应用一些索引。我们可以在字段上定义一个复合索引post_type和post_likes,如下所示:
分析查询现在给出以下结果:
这里非常重要的一点是,在多个字段上定义的化合物索引可用于查询这些字段的子集。例如,假设有一个复合索引{field1,field2,field3}。该索引可用于查询:
- > field1
- > field1,field2
- > field1,field2,field3
因此,如果我们定义了索引{field1,field2,field3},则无需定义单独的{field1}和{field1,field2} indexes。但是,如果我们在查询field2和field2,field3时需要此化合物索引,则如果优化器未选择所需的索引,则可以使用shint()。
提示()方法可用于迫使mongoDB使用索引,我们指定并覆盖默认选择和查询优化过程。您可以将索引中使用的字段名称指定为参数,如下所示:
<span><span><?php
</span></span><span><span>// query to find posts with user_name "Jim Alexandar"
</span></span><span><span>$cursor = $collection->find(
</span></span><span> <span>array("user_name" => "Jim Alexandar")
</span></span><span><span>);
</span></span><span><span>// use explain() to get explanation of query indexes
</span></span><span><span>var_dump($cursor->explain());</span></span>
这样可以确保查询使用post_type和post_likes字段上定义的化合物索引。
多基索引
当在数组字段上完成索引时,称为Multikey索引。再次考虑我们的邮政文件;我们可以在post_tags上应用多基索引。 Multikey索引将索引数组的每个元素,因此在这种情况下,将为post_tags value创建单独的索引:
mongodb ,> tutorial>很快。
但是,由于每个值的索引,数组字段上的索引都必须非常有选择地使用,因为它们会消耗大量内存。
> Multikey Compound Index
我们可以创建一个Multikey Compound索引,但是限制索引中最多可以是一个数组。因此,如果我们将field1作为字符串,而[field2,field3]作为数组,则无法定义索引{field2,field3},因为两个字段都是数组。
在下面的示例中,我们在post_tags和user_name字段上创建索引:
索引限制和注意事项
重要的是要知道,索引不能用于使用正则表达式,否定操作员(即$ ne,$ not等),算术运算符(即$ mod等),$中的JavaScript表达式的查询中使用索引。条款,在其他情况下。
索引操作也有自己的成本。每个索引都占据空间,并且在收集集合上的每个插入,更新和删除操作上都会引起额外的开销。您需要考虑每个集合的读取比率:写比率;索引对重读收藏是有益的,但可能不适合写入较重的收藏。
MongoDB将索引留在RAM中。确保总索引大小不超过RAM限制。如果是这样,将从RAM中删除某些索引,因此查询将减慢。此外,收集最多可以具有64个索引。
摘要
仅此而已。总而言之,如果选择了适当的索引方法,则索引对应用非常有益。在下一部分中,我们将考虑在嵌入式文档,子插件和订购上使用索引。敬请关注!
通过fotolia 图像
经常询问有关mongoDB索引的问题
> MongoDB在数据库管理中索引的重要性是什么?通过为数据提供更有效的途径,它可以显着提高数据库操作的性能。如果没有索引,MongoDB必须执行集合扫描,即扫描集合中的每个文档,以选择与查询语句匹配的文档。使用索引,MongoDB可以将其搜索限制在数据的相关部分,从而减少所需扫描的数据量。这会导致查询响应时间更快,并且CPU使用率较低,这在大型数据库中尤其有益。> MongoDB索引如何工作? mongoDB索引索引可以创建一个特殊的数据结构,该特殊数据结构容纳了集合数据的一小部分。该数据结构包括特定字段或一组字段的值,该值按索引中指定的字段值排序。执行查询后,MongoDB使用这些索引来限制其必须检查的文档数量。当文档的总大小超过可用的RAM时,索引特别有益。>
?查询的性能。其中包括单个字段,化合物,多基,文本,2D和2DDSPHERE索引。每种类型的索引都有特定的目的,用于不同类型的查询。例如,单个字段和化合物索引分别用于单个或多个字段上的查询。 Multikey索引用于数组,并且文本索引用于字符串内容。
>>如何在mongodb中创建索引?
>>您可以使用CreateIndex()方法在MongoDB中创建索引。如果索引尚不存在,则此方法在指定字段上创建索引。该方法采用两个参数:索引的字段或字段和一个允许您指定其他选项的选项文档。
我可以在mongodb中创建多个索引吗? MongoDB的索引。但是,重要的是要注意,尽管索引提高了查询性能,但它们还消耗了系统资源,尤其是磁盘空间和内存。因此,至关重要的是明智地创建索引,并且仅在那些经常查询的领域中。 MongoDB很大程度上取决于您的应用程序的查询模式。经常在排序操作中查询或使用的字段是索引的良好候选者。此外,具有高度唯一性的字段也是索引的良好候选者,因为它们可以在执行查询时大大减少MongoDB的文档数量。您可以使用getIndexes()方法在mongodb中检查索引是否存在。此方法返回集合上所有索引的列表,包括默认情况下创建的_id索引。
我可以在mongodb中删除索引吗?使用DropIndex()方法的mongodb。此方法从集合中删除指定的索引。
> mongoDB中的索引相交是什么? 。当没有单个索引无法满足查询,但两个或多个索引的交集可以。
时,这可能特别有用。>索引对MongoDB的写操作的影响是什么?
>在索引时显着改善了读取操作的性能,它可能会对写操作产生影响。这是因为每次插入或更新文档时,集合上的所有索引也必须更新。因此,集合的索引越多,写操作的越慢。在创建索引时,在阅读性能和写入表现之间找到平衡很重要。
以上是PHP主| mongodb索引,第1部分的详细内容。更多信息请关注PHP中文网其他相关文章!