mongodb创建索引及索引优化效率案例

语法:

db.collection.createIndex(keys, options)

options的属性说明:
在这里插入图片描述
创建索引示例:

单键唯一索引:db.users. createIndex({username :1},{unique:true});
单键唯一稀疏索引:db.users. createIndex({username :1},{unique:true,sparse:true});
复合唯一稀疏索引:db.users. createIndex({username:1,age:-1},{unique:true,sparse:true});
创建哈希索引并后台运行:db.users. createIndex({username :'hashed'},{background:true});

删除索引示例:

根据索引名字删除某一个指定索引:db.users.dropIndex("username_1");
删除某集合上所有索引:db.users.dropIndexs();
重建某集合上所有索引:db.users.reIndex();
查询集合上所有索引:db.users.getIndexes();

查询优化技巧:
第一步:找出慢速查询

  1. 开启内置的查询分析器,记录读写操作效率: db.setProfilingLevel(n,{m}),n的取值可选0,1,2;
     0是默认值表示不记录;
     1表示记录慢速操作,如果值为1,m必须赋值单位为ms,用于定义慢速查询时间的阈值;
     2表示记录所有的读写操作;
    例如:db.setProfilingLevel(1,300)
  2. 查询监控结果
    监控结果保存在一个特殊的盖子集合system.profile里,这个集合分配了128kb的空间,要确保监控分 析数据不会消耗太多的系统性资源;盖子集合维护了自然的插入顺序,可以使用KaTeX parse error: Expected '}', got 'EOF' at end of input: ….find().sort({'natural’:-1}).limit(5)
    第二步:分析慢速查询
    找出慢速查询的原因比较棘手,原因可能有多个:应用程序设计不合理、不正确的数据模型、硬件配置问 题,缺少索引等;接下来对于缺少索引的情况进行分析:
    使用explain分析慢速查询
    例如:db.orders.find({‘price’:{’$lt’:2000}}).explain(‘executionStats’) explain的入参可选值为:
    “queryPlanner” 是默认值,表示仅仅展示执行计划信息;
    "executionStats"表示展示执行计划信息同时展示被选中的执行计划的执行情况信息;
    "allPlansExecution"表示展示执行计划信息,并展示被选中的执行计划的执行情况信息,还展示备选的执行计划的执行情况信息
    第三步:解读explain结果
    queryPlanner(执行计划描述)
    winningPlan(被选中的执行计划)
    stage(可选项:COLLSCAN 没有走索引;IXSCAN使用了索引) rejectedPlans(候选的执行计划)
    executionStats(执行情况描述)
    nReturned (返回的文档个数)
    executionTimeMillis(执行时间ms)
    totalKeysExamined (检查的索引键值个数)
    totalDocsExamined (检查的文档个数)
    优化目标 Tips:
    1. 根据需求建立索引
    2. 每个查询都要使用索引以提高查询效率, winningPlan. stage 必须为IXSCAN ;
    3. 追求totalDocsExamined = nReturned

    测试案例:
 db.orders.find({"useCode":"jack", "orderTime" : 
                   { "$lt" : new Date("2017-08-03T16:00:00.000Z")}}).explain('executionStats')

在这里插入图片描述
可以看到一共检查了1060007个文档,返回了88560个文档,执行了299ms,stage是COLLSCAN,没用索引,
按照上诉优化步骤:
1.找出慢速查询:

db.setProfilingLevel(1,100)

执行之后会出现如下的一个集合:
在这里插入图片描述
然后执行测试语句:

db.orders.find({"useCode":"jack", "orderTime" :
                { "$lt" : new Date("2017-08-03T16:00:00.000Z")}})

查看是否有超过100ms的语句:

db.system.profile.find().sort({'$natural':-1}).limit(5).pretty()

在这里插入图片描述
2.分析慢速查询

 db.orders.find({"useCode":"jack", "orderTime" : 
                   { "$lt" : new Date("2017-08-03T16:00:00.000Z")}}).explain('executionStats')

在这里插入图片描述
发现没有索引。
1建单键索引:

db.orders.createIndex({"useCode":-1})

在这里插入图片描述
快了一些
2.建复合索引

db.orders.createIndex({'useCode':1,'orderTime':1})

在这里插入图片描述
符合我们的优化目标(扫描文档数跟返回数是一样的),但是时间却长了,所以建索引还是要以实践为主,扫描的文档数少不一定能提高效率。
后来发现这个索引更快:

db.orders.createIndex( { useCode: 1 }, { collation: { locale: "fr" } } )
 db.orders.find({"useCode":"jack", "orderTime" :                    { "$lt" : new Date("2017-08-03T16:00:00.000Z")}}).collation( { locale: "fr" } ).explain('executionStats')

在这里插入图片描述
关于此用法介绍的地址:https://docs.mongodb.com/manual/reference/command/createIndexes/index.html
关于索引的建议:

  1. 索引很有用,但是它也是有成本的——它占内存,让写入变慢;

  2. mongoDB通常在一次查询里使用一个索引,所以多个字段的查询或者排序需要复合索引才能 更加高效;

  3. 复合索引的顺序非常重要

  4. 在生成环境构建索引往往开销很大,时间也不可以接受,在数据量庞大之前尽量进行查询优化和 构建索引;

  5. 避免昂贵的查询,使用查询分析器记录那些开销很大的查询便于问题排查;

  6. 通过减少扫描文档数量来优化查询,使用explai对开销大的查询进行分析并优化;

  7. 索引是用来查询小范围数据的,不适合使用索引的情况:

8.每次查询都需要返回大部分数据的文档,避免使用索引

9.写比读多

猜你喜欢

转载自blog.csdn.net/shidebin/article/details/83270486