使用“in”和两个索引之间的数组进行查询时有啥区别?
Posted
技术标签:
【中文标题】使用“in”和两个索引之间的数组进行查询时有啥区别?【英文标题】:What's the difference when query using `in` and an array between two indexes?使用“in”和两个索引之间的数组进行查询时有什么区别? 【发布时间】:2019-05-15 04:26:01 【问题描述】:MongoDB 中包含如下文档的集合:
a: 1, b: 1
a: 2, B: 2
a: 3, B: 3
a: 3, B: 2
a: 2, B: 1
带有 uniq 索引 a_1_b_1
或 b_1_a_1
查询:a: x, b: $in: [....]
哪个索引更好?还是一样?
查询匹配数组如何工作?
更新:
shard key 是否影响查询索引?
分片键:a_1_c_1
额外索引:b_1_a_1
查询:a: x, b: y
-
通过分片键
a_1_c_1
中的a=x
路由到分片,然后使用索引b_1_a_1
在分片中查询
通过分片键路由和查询必须使用分片键?
【问题讨论】:
【参考方案1】:来自 compound indexes 上的 MongoDB 手册部分:
db.products.createIndex( "item": 1, "stock": 1 )
复合索引中列出的字段的顺序很重要。该索引将包含对文档的引用,这些文档首先按 item 字段的值排序,然后在 item 字段的每个值中,按 stock 字段的值排序。
鉴于上述情况,我们可以看到a_1_b_1
将首先由a
分段,然后由b
分段,而b_1_a_1
将首先由b
分段,然后由a
分段。
现在让我们检查您的查询:a: x, b: $in: [....]
请注意,此查询匹配特定的a
值和一系列可能的b
值。在索引a_1_b_1
中,索引扫描将仅限于匹配的a
块,并且将在其中搜索所有b
值;但是,如果您使用索引b_1_a_1
,则索引扫描必须在不同的b
块之间“跳转”并在每个块中搜索匹配的a
值。
访问“靠近”在一起的数据通常效率更高,因此您需要选择匹配文档更有可能位于其中的索引。在这种情况下,将所有文档放在同一个 a
块中可能是一个更好的选择,因为发生的“跳跃”应该更少,因此您应该使用索引 a_1_b_1
。
然而,这过于简单化了。实际的性能影响可能可以忽略不计,尤其是在a
和b
的可能范围非常小的情况下。
您还应该考虑一个额外的因素:查询前缀。如果您发现自己有时只使用a
值执行查询,那么您应该选择索引a_1_b_1
。同样,如果您有时只使用b
值执行查询,那么您可能应该选择b_1_a_1
。
这是因为如果您的查询不完全匹配索引但匹配该索引的前缀,则该索引仍然适用。因此,在索引a_1_b_1
中,您可以对a: x, b: $in: [....]
和a: x
执行高效查询,但您无法对b: $in: [....]
执行高效查询。
最后,通常还可以利用index intersection 来拥有两个独立的索引a_1
和b_1
,从而在性能和灵活性之间取得平衡。
考虑到以上所有因素,我不建议您过多关注索引性能,直到您的数据大小开始需要它。毕竟,您可以根据需要删除旧索引并构建新索引。使用目前有效的方法,随着时间的推移监控性能,并在看起来可能超出当前使用的情况时重新评估。
【讨论】:
感谢您的解释,集合中有数十亿个文档,a
和 b
都有很大的范围。还有一个问题是:如果集合按索引b_1_a_1
分片,查询a:x, b: $in: [..]
是否会作为b: x, a: y
的倍数执行?
@nFeng 不幸的是,我对分片集合没有任何经验,对它们的工作原理只有粗略的了解,所以我没有答案。以上是关于使用“in”和两个索引之间的数组进行查询时有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章