MongoDB索引使用注意事项、执行计划(explain)

一、Mongo使用索引注意事项

1、低效率查询

    1)、$where和$exists完全不能走索引

      首先$where是完全不能使用索引的,而$exists也是不可以使用稀疏索引进行查询,因为不存在的字段和值为null的存储方式是一样的,不能有效的过滤掉为null的字段。

    2)、$ne取反操作效率很低

      取反操作即使可以走索引也需要对全索引进行查询,否则不知道是否还有取反的数据。

    3)、$not、$nin

      $not在简单的条件下可以进行反转后走索引,但是大多数情况下会进行全表扫描。而$nin一定会走全表扫描,需要注意。

2、范围查询

    如果需要进行范围查询的时候,可以走索引(底层树的特点),但是如果同时存在精确查找和范围查找的时候,需要将精确查找放在前面,先过滤掉大部分的数据,再进行范围查找。若两个查找使用的是两个索引时,则会先使用精确查询的索引,再查询范围字段的索引。

3、$or、$in

    使用$or操作本质上是执行了多次查询,然后将结果集进行合并(去重),所以一般来说查询效率也是比较低的。$in操作在返回数据的时候不能控制返回数据的顺序,除非进行排序操作。

4、嵌套文档或数组

1)、嵌套文档

  在一个嵌套文档的子字段上进行索引,可以使用如下方式:

    db.user.ensureIndex({"parant.childField1":1});   # 在parant的childField1字段上创建索引

  需要注意的是: 创建子索引可以和父索引一起混合使用;

                            在父字段上创建的索引,在子字段查询的时候不生效;反之在子上建立的索引,父也不能使用;

 2)、数组

  MongoDB中的数组在创建索引的时候是比较特殊的,在数组上创建索引其实是创建了一个索引条目,即若该数组下有50个元素则会生成50个索引条目,与单个字段的索引元素完全不同,所以对程序的性能影响较大(crud操作的时候都需要对索引的文档进行操作,相当于操作了普通索引的50个文档),并且数组存放了多少条数目是完全不确定的,所以个人建议不要在数组上建立索引,对程序而言性能影响完全不可控制。,创建方式如下:

    db.user.ensureIndex({"parant.childArrFeild1":1});  # 对parent(数组)的某一个数组字段建立索引

  而在对数组建立索引本身该字段没有索引,比如comments字段下有50条数据则建立了50个索引,则若需要在特定的下表的索引上建立索引可以使用(比如可能有特殊需求,比如第一条评论进行操作等),如下:

  db.user.ensureIndex({"parant.1.childArrFeild1":1});  # 值对第一个数组元素的某一个字段创建索引

需要注意: 一个索引只能有一个数组字段,就是为了防止在多个数组上创建索引则索引会成几何倍数的增加(可能使用者不知道);当在一个文档上建立了一个数组索引,则会被标记为多键索引,并且当升级为多键索引的时候,则不能再恢复到单键索引,哪怕是删除了数组字段和索引,除非将整个集合删除重建。多键索引的速度回慢与单键索引就是由于Mongo需要根据标志,对数据进行去重操作。

5、索引基数

    索引基数是指某一个字段的值的重复性,比如性别字段,一般就两三个值,则索引基数是非常低的,则在其上面建立索引也是效率非常低的(只能排除一般的数据)。索引应该将索引建立在索引基数较高的字段上,并且如果是符合索引,则应该从左到右排列索引基数由高到低的字段(业务因素除外)。

 

二、执行计划(explain)

     与mysql一样,需要查询sql执行的过程,或者需要对慢sql进行分析,则离不开执行计划的查询。

     不同的版本执行计划变动较大,后续更新。

你可能感兴趣的:(数据库)