资讯专栏INFORMATION COLUMN

一起飞系列之:浅谈Mongodb的索引优化

arashicage / 3388人阅读

摘要:栗子在没有索引的情况下查询全部北京车牌号码返回结果如下哭表示全文检索。该数据集包含了数据,其中属于北京车牌。栗子添加索引因为我们只是需要得到北京市的车牌号码,所以在我们的例子中涉及到了个索引信息,一个是城市另外一个就是车牌号码。

难度水平:初中级
适用人群:对Mongodb数据查询已经一定经验的码农,了解explain()的用法。
阅读时间:10分钟
缘起

本来是打算回答一个网友的问题,不过回复框太小而且功能不全(差评^o^),于是乎就成就了本文的产生。在这里我主要就是想跟大家分享一下我对Mongodb索引的粗浅理解,抛砖引玉,希望能对一些人有所帮助。

对于数据库的索引相信大家都不陌生,主要功能就是在数据库内提高针对特定信息的访问速度。那么在Mongodb里面索引是怎样被引用跟查找的呢?下面我来通过几个例子给大家分享一下我的心得体会。

Mongodb基础数据查询

举个栗子,按照城市查询车牌号码系统。为了方便演示,我在所有查询后面都加入了explain()函数。要注意explain的返回结果集中的一下选项:

cursor - 索引项

n - 查询结果的条目总数

nscanned - 扫描并读取的索引条目数(index)

nscannedObjects - 扫描并读取的全文条目数(documents)

indexOnly - 是否使用了covered indexes功能,宝宝不哭,后面有详述。

millis - 查询用时,单位是毫秒。


栗子1: 在没有索引的情况下查询全部北京车牌号码
db.carLicence.find({city:"Beijing"}).explain()

//返回结果如下:
{
  "cursor" : "BasicCursor",
  "n" : 1563247,
  "nscannedObjects" : 96539732,
  "nscanned" : 96539732,
  "indexOnly" : false,
  "millis" : 156, // 哭!
}

BasicCursor表示全文检索。上面的例子说明,在没有索引的情况下,该查询语句查询了整个数据集carLicence。该数据集包含了96539732数据,其中1563247属于北京车牌。整个用时为156毫秒.

小结: 一定要避免没有索引的全文查询


栗子2: 在没有索引的情况下,使用limit(1000)来查询北京车牌号码
db.carLicence.find({city:"Beijing"}).limit(1000).explain()

//返回结果如下:
{
  "cursor" : "BasicCursor",
  "n" : 1000,
  "nscannedObjects" : 18476396,
  "nscanned" : 18476396,
  "indexOnly" : false,
  "millis" : 85, // 擦干眼泪!
}

这个例子说明,Mongodb在搜索满1000个条目之后就停止继续检索了。

小结: 尽量使用limit()来处理你的数据查询


栗子3: 添加索引

因为我们只是需要得到北京市的车牌号码,所以在我们的例子中涉及到了2个索引信息,一个是城市city,另外一个就是车牌号码licence。那么我们来给这2个信息添加索引,来查询全部北京车牌号码。

注意:给2个以上的字段建立索引叫做Compound Index复合索引[多字段索引),hashed字段不能创建索引。建立方法如下db.carLicence.ensureIndex( { "city": 1, "licence": 1 } )
db.carLicence.find({city:"Beijing"}).explain()

//返回结果如下:
{
  "cursor" : "BasicCursor city_1_licence_1",
  "n" : 1563247,
  "nscannedObjects" : 1563247,
  "nscanned" : 1563247,
  "indexOnly" : false,
  "millis" : 47, // 只剩 擦!
}

相信看到这里,大家已经对所有的功效有了一个初步的认识了。

小结 - 尽量给涉及到的条目建立索引

那么,indexOnly的covered indexes功能会有什么样的提高呢?好让我们来看最后这个例子。


栗子4: 使用覆盖索引 Covered Indexes
db.carLicence.find({city:"Beijing"}, {licence:1, _id:0}).explain()

//返回结果如下:
{
  "cursor" : "BasicCursor city_1_licence_1",
  "n" : 1563247,
  "nscannedObjects" : 0,
  "nscanned" : 1563247,
  "indexOnly" : true, // 变了 变了 !
  "millis" : 41, // 擦!擦!擦!
}

最后这个例子涉及到了covered indexes(覆盖索引),通常来说,覆盖索引只在查询文档的索引字段时候使用。但是有几个特性跟附加条件要遵循.

查询字段必须是索引字段

要去掉_id因为是返回的Object. 通过_id:0来实现。

索引字段不能是. 也就是说在explain()里面,如果isMultiKey:true的话indexOnly一定是false.

另外一个就是在最后一个栗子里面nscannedObjects是零,这是因为我们只是提取了索引里面的目录条licence,并不需要每一条的全部数据(document),加上"indexOnly" : true,所以, Mongodb直接从索引里面提取了数据licence,不用再去查询物理数据集carLicence得到相关全文信息。所以nscannedObjects为零。

小结 - 在只提单字段数据的前提下,要给对应的但字段建立索引索引

结语

粗浅的分析一下我对索引的理解跟一些优化体验。有兴趣的朋友可以共通研究。最后说一句,善用explain()能对你的优化查询有很大的益处。加油!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/18842.html

相关文章

  • 【推荐】最新200篇:技术文章整理

    摘要:作为面试官,我是如何甄别应聘者的包装程度语言和等其他语言的对比分析和主从复制的原理详解和持久化的原理是什么面试中经常被问到的持久化与恢复实现故障恢复自动化详解哨兵技术查漏补缺最易错过的技术要点大扫盲意外宕机不难解决,但你真的懂数据恢复吗每秒 作为面试官,我是如何甄别应聘者的包装程度Go语言和Java、python等其他语言的对比分析 Redis和MySQL Redis:主从复制的原理详...

    BicycleWarrior 评论0 收藏0
  • 【推荐】最新200篇:技术文章整理

    摘要:作为面试官,我是如何甄别应聘者的包装程度语言和等其他语言的对比分析和主从复制的原理详解和持久化的原理是什么面试中经常被问到的持久化与恢复实现故障恢复自动化详解哨兵技术查漏补缺最易错过的技术要点大扫盲意外宕机不难解决,但你真的懂数据恢复吗每秒 作为面试官,我是如何甄别应聘者的包装程度Go语言和Java、python等其他语言的对比分析 Redis和MySQL Redis:主从复制的原理详...

    tommego 评论0 收藏0
  • 墙裂推荐:搜云库技术团队,面试必备技术干货

    摘要:今天整理了一下近大半年以来的一些文章,和我的预期一样,很多文章我都忘记自己曾经写过了,这个记录的过程让我也有了新的理解。希望大家,收藏,点赞,加转发。 今天整理了一下近大半年以来的一些文章,和我的预期一样,很多文章我都忘记自己曾经写过了,这个记录的过程让我也有了新的理解。希望大家,收藏,点赞,加转发。 面试必备 面试必备:深入Spring MVC DispatchServlet 源码...

    SegmentFault 评论0 收藏0
  • 墙裂推荐:搜云库技术团队,面试必备技术干货

    摘要:今天整理了一下近大半年以来的一些文章,和我的预期一样,很多文章我都忘记自己曾经写过了,这个记录的过程让我也有了新的理解。希望大家,收藏,点赞,加转发。 今天整理了一下近大半年以来的一些文章,和我的预期一样,很多文章我都忘记自己曾经写过了,这个记录的过程让我也有了新的理解。希望大家,收藏,点赞,加转发。 面试必备 面试必备:深入Spring MVC DispatchServlet 源码...

    Neilyo 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<