如果你有一个双复合指数{A:1,B:1},这是有道理的,我认为,如果你在单独的B查询索引将不会被使用(即你不能“跳过”在你的查询 )。 如果你在一个单独的查询索引然而,将使用。
然而,由于三重复合索引{A:1,B:1,C:1}我的解释命令显示,当你在A和C查询使用索引(即你可以“跳过”在您的查询B)。
蒙戈如何使用对AC查询的ABC指数,以及如何有效的是在这种情况下,指数?
背景:
我使用的情况是,有时我想在A,B,C查询有时我想在A,C查询。 现在,我应该在A,B,C仅创建1个指数或我应该创建一个在A,C和一个在A,B,C?
(这是没有意义的创建一个索引,C,B,因为C是一种具有良好的选择性多键索引)。
底线/ TL; DR:索引b
可以是“跳过”,如果a
和c
被查询相等或不等的,但不是,例如,用于排序上c
。
这个问题问得好。 不幸的是,我无法找到任何权威回答这个更详细。 我相信这样的查询性能在过去几年有所改善,所以我不会在话题信任旧材料。
整个事情是相当复杂的,因为它依赖于选择性上的指标,你是否查询平等,不平等和/或排序,那么explain()
是你唯一的朋友,但这里有一些东西,我发现:
警告 :现在会给出的实验结果,推理和猜测的混合物。 我可能会被拉伸凯尔的比喻太远了, 我甚至可能是完全错误的 (和不幸的人,因为我的测试结果松散匹配我的推理)。
很显然,A的指数可以使用,这取决于A的选择性,肯定是非常有帮助的。 “跳过” B可以是棘手的,或没有。 让我们记住这类似于凯尔的食谱例如 :
French
Beef
...
Chicken
Coq au Vin
Roasted Chicken
Lamb
...
...
如果你现在问我找到了一些法国的菜叫“夏多布里昂”,我可以使用索引A
和,因为我不知道的成分,必须扫描所有的菜A
。 在另一方面,我知道的菜每个类别中的列表是通过指数来分类C
,所以我将只需要查找的字符串中的每个成分列表开始,说:“查”。 如果有50种成分,我将需要50个查找,而不只是一个,但比其扫描每个法国菜好很多!
在我的实验中,数量比不同值的数量少了很多b
:它从来没有seemd超过2。但是,我测试了这只跟单托收,它可能具有与选择性做b
-指数。
如果你要我给你的所有的法国菜肴按字母顺序排序列表 ,不过,我会很麻烦 。 现在,该指数C
是毫无价值的,我不得不合并排序所有这些索引列表。 我将不得不扫描每一个元素这样做。
这反映在我的测试。 这里有一些简单的结果。 原来收藏有日期时间,整数和字符串,但我希望让事情变得简单,所以它现在所有的整数。
本质上,只有两个类的查询:那些nscanned
<= 2 * limit
,以及那些必须扫描整个集合(120K文档)。 该指数是{a, b, c}
// fast (range query on c while skipping b)
> db.Test.find({"a" : 43, "c" : { $lte : 45454 }});
// slow (sorting)
> db.Test.find({"a" : 43, "c" : { $lte : 45454 }}).sort({ "c" : -1});
> db.Test.find({"a" : 43, "c" : { $lte : 45454 }}).sort({ "b" : -1});
// fast (can sort on c if b included in the query)
> db.Test.find({"a" : 43, "b" : 7887, "c" : { $lte : 45454 }}).sort({ "c" : -1});
// fast (older tutorials claim this is slow)
> db.Test.find({"a" : {$gte : 43}, "c" : { $lte : 45454 }});
你的情况可能会有所不同。
可以查看在A和C作为查询查询在A的一种特殊情况(在这种情况下,索引将被使用)。 使用索引比具有加载整个文件更有效。
假设你想获得的所有文档A和13之间的5和8之间7,和C。
如果你曾在一个只有一个索引:数据库可以使用指数7和13之间,A选择文档,但,确保C为5和8之间,那就要获取相应的文档了。
如果您对A,B和C的索引:数据库可以使用索引,选择了7和13既然已经存储在索引中的记录C的值之间的文件,它可以判断是否correponding文件还匹配MC准则,而无需检索这些文件。 因此,你会避免磁盘读取,具有更好的性能。