06-MongoDB 查询索引优化-2-索引优化案例

一、查询场景优化

1.1 SQL语句

  • 查询语句如下:
db.getCollection('multobj').find({
  $and: [
    {
      "time": {
        "$gte": ISODate("2019-04-01T00:00:00Z"),
        "$lte": ISODate("2019-05-01T23:59:59Z")
      }
    },
    {
      "sourceType": "hikCamera"
    },
    {
      "targetType": "face"
    },
    {
      "sourceId": {$in:["1"]}
    } 
  ]
}).sort({time:-1}).limit(100) 

1.2 场景

  • 简单描述一下业务场景,我们sourceId这个字段,可能会传输多个,是一个比较离散的字段,targetType和sourceType都有多种类型,
    时间过滤是一定会带上的。

1.3 查询结果

在优化索引之前,在一个1000万数据的集合中,满足这个条件的记录是3.5W,这个查询耗时500余秒。非
常慢。执行计划中截图如下,使用的是sourceId+time的组合索引,我们看到这个过程扫描了24W个文档,回到上一篇文章,我们知道这样
的查询肯定是不行的,即使在数据量小的时候没有暴露问题,数据量上去了肯定很慢。

image
image

1.4 调整索引

  • 调整索引。我创建了一个新的索引,索引字段是:sourceId+sourceType+targetType+time(前三个字段离散度高的放前面)。

1.5 调整后查询结果

  • 然后再次查询,耗时是30毫秒,非常快。我们看下面的查询计划。结果显示这一次查询的情况非常好,扫描的文档数和索引数就是我们需要查询的
    数量,数据库几乎没要做太多冗余的工作,因此非常快速。

image

二、如何选择索引

2.1 选择索引的字段

  • 通常来说,选择索引的字段离散度较大比较好,如果一个字段离散度不大,建索引是没什么意义的。不过我感觉这个规则比较适合单键索引,在组合索引中则不一
    定,比如上面我优化的组合索引,有一个字段的值只有三四种,不过或许他的离散度更大的话,索引的效果会更好。

2.2 索引顺序

  • 组合索引的顺序按照{精确匹配字段,排序字段,范围查询字段},这样的索引排序会更为高效。最前面的精确匹配字段离散度越大越好,因为那样索引就能定位到小部分数据,
    比如之前优化的索引中sourceId这个字段在数据库中是离散度比较大的,这样就能过滤掉大部分数据。精确匹配字段部分可能有多个,像上面的
    sourceId、sourceType和targetType都是精确匹配字段,排序字段是time,最后的范围字段就是一些不等式的条件。结合这个来看
    sourceId+sourceType+targetType+time这个索引其实只用到了前面2个部分,没有范围字段。这里还可以给一个例子,在另一个查询场景下我的查询包含5个字段,
    这里简述为A、B、time、D、E,其中A是精确匹配的字段,B是范围字段,DE在数据库中95%的数据都包含,有这样的一个场景,查询逻辑是
    A=a and (B>b1 and B <b2) and D=d and E=e and sort(time),我优化的索引是A+time+B,因为在数据库中95%的记录都都满足 D=d and E=e,因此最后2个字段没有建立
    索引,优化这个索引之后,查询性能也得到了显著的提升。

2.3 索引原则

  • 最佳索引必须包含查询中所有可以做过滤及需要排序的字段。
  • 如果索引中的等值或者范围查询字段不能过滤出Collection中90%以上的文档,那么把它移除索引估计会更好一些,这也是我们尽量选择比较离散的字段建索引的原因。
  • 按照 {等值,排序字段,范围字段}的顺序创建联合索引。
  • 等值测试:在索引中加入所有需要做等值测试的字段,任意顺序(不过我觉得离散度高的在前面比较好)。
  • 排序字段:(多排序字段的升/降序问题 )根据查询的顺序有序的向索引中添加字段。
  • 范围过滤:以字段的基数(Collection中字段的不同值的数量)从低到高的向索引中添加范围过滤字段。

2.4 索引竞争与选择

  • 我们数据库中往往创建了多个索引,那么数据库如何保证找到最佳的索引呢?这里面包含一个存储引擎对索引的竞争选择的问题,这里有一篇非常好的文章,建议大家参
    考,我看了之后感觉受益匪浅。MongoDB组合索引的优化中的MongoDB的索引选择机制这一小节。

三、小结

  • 本文给了一个简单的索引优化案例,给出了一般组合索引创建遵循的基本原则,具体到业务场景还需要具体分析。索引并不是越多越好,而是越少越好,索引会占据
    不少内存资源,也会影响写入和修改的性能,在创建索引的时候我们需要考虑这个索引是不是值得去创建。
  • 目前我们还没有涉及到查询计划中比较深入的分析,以及慢查询日志中相关的分析,这一块在后续慢慢更新。

四、参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值