杰西JrYu戴维斯10GEN工程师从事MangGDB、Python和TrnADO。在DunGub中创建MyGDB中的复合索引的最佳方法和索引中的最佳字段顺序。使用解释()的输出来验证MunGod的实际性能和索引选择机制。对B查询优化器进行了分析。
设想的项目是在MunGDB上构建一个类似于DISQUs的注释系统(尽管DISQS使用PASGRESS,它不影响我们的讨论)。这里可能有成千上万条注释,但是我们先从4个简单的注释开始。每个注释有三个属性:时间戳、匿名和RA。叮叮声。
这里的查询是匿名=false和时间戳注释24,查询结果按等级排序。我们将在3个步骤中完成查询优化,并通过MunGDB的解释()来考虑索引。
查询的结果显然是3。但是,这里的重点是看MangGDB是如何通过解释()来实现查询的。
首先看看如何读取MangGDB的查询计划:首先,查看CURSORE的类型。Basic Curror可以称为警告标志:这意味着MangGDB将对数据集进行完整的扫描。当数据集包含数以千万计的信息时,这是完全不可行的。因此,我们需要T。o向时间戳添加索引:
光标的类型现在变得明显的是BtReCuuor TimeStPy1(TimeStpPy1是前面定义的索引名称)。Nscanned从4下降到3,因为这里Mango使用索引跳过范围之外的文档,直接指向需要查询的文档。
对于定义索引的查询:NSCANDEND表示Mongo扫描字段索引中的条目数,而NScNeND对象表示在最终结果中查询的文档数。N表示返回的文档数。NSCAN对象至少包含所有返回的文档。尽管Mongo清楚地指出了绝对匹配文件的索引,但是可以得出结论,nScNdNe= nScInnDistObjs= n。对于简单查询,您可能期望3个数字相等。这意味着您已经完成了MangGDB用法的完美索引。
但是在什么情况下NSCN大于N显然,当Mongo需要检查指向不匹配查询的字段的某些索引时,例如,我需要筛选出匿名=真文档:
从解释()的输出中,虽然N从3下降到2,但是NSnIndex和nScNeDdObjor的值仍然是3。Mongo将时间戳的索引从2扫描到4,其中包含了所有的匿名=真/假的情况。在检查文档之前,没有人会被过滤。
那么,我们怎样才能回到完美的nScNdNe= nScNeNdObjs= n这里我们尝试一个关于时间戳和匿名的复合索引:
现在情况更好了:NScNeNdObjts已经从3下降到2,但是NScNeND仍然是3!Mongo仍然从时间戳2到4进行了完整的索引扫描。当然,当匿名索引被检查以发现它的值是真的时,Mongo选择跳过而不进行文档扫描。所以这就是NSCAN的值只有2的原因。
我们能改善现状,减少NSCAN到2吗您可能已经注意到:定义索引顺序存在问题。是的,它应该是匿名的、时间戳而不是时间戳、匿名的:
MangGDB复合索引的关键字序列问题与其他数据库相同。如果匿名被用作索引中的第一个关键字,Mongo将直接调用到匿名= false文档,用于时间戳2到4范围。
第一部分是对MangGDB复合索引的优化思想的简要理解,但事实上,这种情况只存在于理想中。
不必设想匿名在索引中是否有价值。例如,如果我们在系统上每天有数以千万计的评论和数以千万计的查询,那么减少NSCANDEND将极大地增加系统的吞吐量。但是如果匿名部分很少被使用。n是一个索引,很明显,它可以从索引中移除,以节省频繁使用的字段。另一方面:双字段索引肯定占用比单个字段索引更多的内存,因此单字段索引无疑更具记忆性。真实性占总收益的很大一部分。现在我们必须综合考虑,我们还必须看一下MangGDB指数的选择机制。
让我们从一个有趣的事情开始:我们没有删除前一个例子中的索引,所以MangGDB永远是我们构建的三个索引中的首选。为什么会这样呢
MunGDB的优化器将在比较中选择更好的索引。首先,它为查询生成一个初步的最佳索引;第二,如果不存在最佳索引,则尝试选择性能最好的索引;最后,优化器记住所有相似的查询选择(仅大文件CHA)。NGE或索引变化。
优化器如何定义查询的最佳索引。最佳索引必须包含可在查询中过滤和排序的所有字段。此外,用于范围扫描和排序的任何字段必须紧邻进行等效查询的字段。如果有不同的最佳索引,则Mongo WI。在这种情况下,匿名、时间戳显然是最好的索引,所以选择很快。
考虑到这个非常苍白的表达式,让我们详细地了解这两个部分是如何工作的。当优化器需要选择一组没有特殊优势的索引中的一个时,它会收集相关查询的所有相关索引,并选择第一个完成索引。
所有三个索引都是相关的,因此MangGDB以任意顺序加入三个索引,并依次标记每个索引的条目:
在这个竞争中,右边的索引显然比其他两个更完整,然后它将永远存在于下一个竞争之前的最佳索引。简而言之:在多个索引的情况下,MangGDB更倾向于具有最低扫描值的索引。
现在我们有一个完美的时间戳索引在2到4之间,我们最后的步骤是排序。
这通常是以前做过的,现在也是很好的:nScNdNe= nScNeNdObjs= n。但是不要忽略这个:SCAN and Orth=真。这意味着MangGDB将所有查询结果放入内存中,对它们进行排序,然后同时输出它们。但是,我们必须考虑:这将占用大量的麻木。Mongo服务器和RAM的ER,而不是输出批处理结果,而是将它们全部放在内存中,并将输出的资源与应用服务器进行严重竞争。最后,Mongo将对数据施加32 MB约束并将其排序在内存中。尽管只有4个CO。在我们的讨论中,我们已经设计了数以千万计的系统。
那么我们如何处理Snand命令我们需要添加一个索引,这样Mongo就可以直接进入ANONYALY=FALSE部分,按需要的顺序扫描这个部分:
Mongo使
哈尔滨网站优化用这个指数吗当然不会,因为这个索引不会赢得竞争中最小的nSnDead索引。优化器无法识别哪个索引对排序有用。
语句提示中的争议类似于CuraTealIndex。现在NSCANDEND=3,但SCANDENATORD = FALSE。现在Mongo将反向查询匿名、分级索引,以正确的顺序获取注释,然后检查每个文件的时间戳是否在范围内。
这就是为什么优化器不选择这个索引来执行旧的匿名、时间戳索引,它具有低N扫描但完全在内存排序中的原因。
我们以N扫描为代价来解决SCANDENATORD =真的问题;既然NSCAN不能减少,我们能减少nSnCnbe对象吗我们将时间戳添加到索引中,这样Mongo就不必从每个文件中获取它:
当然,您必须考虑是否将时间戳添加到索引中,因为时间戳给内存带来的额外空间不会花费任何代价。
在字段的基数(集合中的字段的不同值的数目)中,将索引范围的字段从低到高添加。
当然,这里有一条规则:如果索引中的等值或范围查询字段不能过滤集合中超过90%的文档,最好删除索引估计。如果集合中有多个索引,则必须有提示MangOS。
有很多因素决定了复合索引的建立。虽然本文不允许您直接确定一个最优索引,但它确实允许您缩小索引创建的选择。
如果您想感受大数据的魅力,北京新云南皇冠假日酒店将主办HBTC 2012(Hadoop大数据技术会议2012),这是11月30日至12月1日在中国大数据领域最纯粹的科技活动。京。欢迎热爱开源的朋友!