.net中根据索引取集合中的值_Mongo分片集群环境中是如何查询和索引的

从应用程序的角度来看,查询分片集群和查询单个mongod没什么区别。这两种情况下,查询接口和迭代结果集的过程是一样的。但在外表之下,两者还是有区别的,我们需要从细节层面进行了解。

分片查询类型

假设正在查询一个分片集群,为了返回一个恰当的查询响应,mongos要与多少个分片进行交互。稍微思考一下,就能发现这与分片键是否出现在查询选择器里有关。配置服务器(就是mongos)维护了一份分片范围的映射关系,就是我们在前面博文中描述的块。如果查询包含分片键,那么mongos通过数据块能够很快定位哪个分片包含查询的结果集。这个称为针对性查询(targeted query)

但是,如果分片键不时查询的一部分,那么查询计划器就不得不访问所有分片来完成查询。这称为全局查询或分散/聚合查询(scatter/gather query)。下图描述了这两种查询。

针对任意指定的分片集群查询,explain命令能显示其详细查询路径。首先看一个针对性查询,此处要查询一个随机文档。

1d120965ed1b63ba22b13c480f6f0686.png

explain结果清晰地说明了查询命中了一个分片-分片A,返回一个文档。查询选择器很聪明地使用了分片键前缀的子集来路由查询。

那么全局查询又会是怎样呢?你可以方便地使用explain命令。下面就是一个根据filename字段进行查询的例子,其中既没有用到索引,也没有用到分片键:

selector={filename:"sheet-1"}db.spreadsheets.find(selector).explain(true)

执行结果如下:

38e62c8f92792688d722d5927b452240.png
0d89ff4d0671ad1e97fd48c5c2c77324.png
d840727789f29817bd64fd9eab55b5ad.png
b778f4e0f72e286022c22ea164d7eb11.png
c1afc202ca2127265d8f330cbdb8c979.png

如你所想,该全局查询在两个分片上进行了表扫描,如果查询与你的应用程序相关,你一定想在filename上增加一个索引。无论哪种情况都会搜索整个集群以返回完整结果。一些查询要求并行获取结果集。这就要求在mongos路由器上合并结果。没有索引,这样的额查询会非常低效,并且会屡遭禁止。因此,在下面的查询最近创建的文档的例子里,你就先要创建必要的索引。

db.spreadshetts.ensureIndex({updated_at:1})

正如预期的那样,游标扫描了每个分片的updated_at索引,一次返回最近更新的文档。

更有可能出现的查询时返回某个用户最新修改的文档。同样,你要创建必要的索引,随后发起查询:

db.spreadshetts.ensureIndex({username:1,updated_at:-1})

关于上面的查询计划,有几个需要注意的地方。首先,该查询指向了单个分片。因为你指定了分片键username,所以查询路由器可以找出哪个分片包含了相关的块。随后你就会发现排序并不需要访问所有的分片;当排序查询中包含分片键,所要查询的分片数量通常都能有所减少。

第二个需要注意的地方是分片使用了{username:1,updated_at:-1}索引来执行查询,这说明了一个很重要的内容,即分片集群是如何处理查询的。通过分片键将查询路由给指定分片,一旦到了某个分片上,有分片自行决定使用哪个索引来执行该查询。在为应用程序设计查询和索引时,请牢记这一点。

索引

有时,如果不确定某个查询时怎么解析的,可以试试explain()。通常这都很简单,但是在运行分片集群时,有几点关于索引的内容应该牢记在心,下面会逐个进行说明。

(1)每个分片器维护了自己的索引。这点应该是显而易见的,当你在分片集合上申明索引时,每个分片都会为它那部分集合构建独立的索引。例如,在上一篇博文中,通过mongos发起可db.spreadsheets.ensureIndex()命令,每一个分片都单独处理了索引创建命令。

(2)由此可以得出一个结论,每个分片上的分片集合都应该拥有相同的索引。如果不是这样的话,查询性能会很不稳定。

(3)分片集合只允许在_id字段和分片键上添加唯一性索引。其他地方不行,因为这需要在分片间进行通信,实施起来和复杂,而且相信这么做速度也很慢,没有实现的价值。

一旦理解了如何进行查询的路由选择,以及索引时如何工作的,你应该就能针对分片集群写出漂亮的查询和索引了。

原文链接:https://blog.csdn.net/wanght89/article/details/77942852
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值