MongoDB学习04–性能分析及索引操作

3月 16th, 2012
MongoDB中的性能分析及索引操作

  1. 性能分析函数explain();
    1. 语法:cursor.explain(verbose),verbose为true或者1的时候会输出所有的执行计划和旧的执行计划;
    2. 一般是跟在find()操作后使用(eg:db.mycoll.find().explain()),它的执行速度决定于实际查询的速度,尽管explain()会额外生成一系列候选的执行计划,但是跟实际查询的性能相差不大;
    3. explain函数的输出结果;                                                          
    4. explain()函数输出结果含义:
      1. cursor:查找使用的cursor类型和索引名称;
      2. isMultiKey:是否是联合索引;
      3. n:返回记录的个数;
      4. nscannedObjects:遍历的文档对象的个数;
      5. nscanned:遍历的文档的个数;
      6. nscannedObjectsAllPlans: <num>;
      7. nscannedAllPlans: <num>;
      8. scanAndOrder: <boolean>;
      9. indexOnly: <boolean>;
      10. nYields: <num>;
      11. nChunkSkips: <num>;
      12. millis:消耗的时间,单位是ms;
      13. indexBounds:索引的范围,如果为空表示没有用到索引;
      14. llPlans:产生的所有的候选的执行计划;
      15. oldPlan:旧的执行计划;
      16. server:主机名和端口号<host:port>;
  2. 创建/删除索引,及前后效率的对比;
    1. 创建索引语法:db.mycoll.ensureIndex(keypattern[,options]);
      1. keypattern:是索引的键;
      2. options:可以取name,unique,dropDups,sparse等值;
      3. 只有在某个列上没有索引才会创建,如果存在索引的话就不再创建;
      4. 默认创建的是b-tree索引;
      5. 可以在子文档上创建索引:db.mycoll.ensureIndex({“object.attritude”:1});
    2. 没有创建索引时,查找name=index10000的效率:db.index.find({“name”:”index10000″}).explain();使用的是BasicCursor即没有索引,扫描了10w条记录后返回1条记录,消耗了192ms;              
    3. 在name列创建一个名为idx_index_name的索引:db.index.ensureIndex({name:1}, {name:”idx_index_name”}),如果不指定第二个参数中的name的话,则系统会自动生成一个索引的名称;          
    4. 查看创建索引后的效率,发现使用了Btree索引,一共扫描一条记录,返回1条记录,并且瞬间返回;                                            
    5. 删除索引语法:db.mycoll.dropIndex(index),可以根据名称删除索引,或者根据创建时指定的键值;
      1. db.mycoll.dropIndex(“indexName”):根据索引名称删除;
      2. db.mycoll.dropIndex({ “indexKey” : 1 }):根据key值删除索引;
      3. 如果要删除某个集合下所有的索引,则使用db.mycoll.dropIndexes(),但是无法删除系统自动创建的基于_id列的索引,它由数据库自己维护;
    6. 重建索引:db.mycoll.reIndex(),是把原来的索引删掉后重建;                                                        
  3. 唯一索引:
    1. 语法:db.mycoll.ensureIndex(keypattern, {unique:true});
    2. 创建一个基于name列的唯一索引unq_index_name:db.index.ensureIndex({name:1}, {name:”unq_index_name”, unique:true});
    3. 如果某一个列上已经存在的重复值,在这样的列上创建唯一索引的话可以使用dropDups选项,这样系统会保留第一条记录,删除剩下重复的记录:db.mycoll.ensureIndex(keypattern, {unique:true, dropDups:true});
    4. 如果某一个列是唯一列,插入数据时没有插入此列的话会保存一个null值,一个唯一列中只能有一个null值;(这点与关系型数据库不同,关系型数据库中唯一列中可以保存null值,但是在mongodb中null值作为了一个值来比较)
  4. 组合索引:
    1. 语法与普通索引相同,只是需要多指定几个列:db.mycoll.ensureIndex({key1:value1, key2:value2, …});
    2. 键后面的数字表示索引的存储顺序,其中1表示升序,-1表示降序.在随机访问的时候意义不大,但是在排序或者是范围查询时很重要;
    3. 如果在a,b,c三列上创建了这索引,则以a,ab,abc开头的条件都可以使用到此索引;
  5. 稀疏索引:
    1. Sparse indexes only contain entries for documents that have the indexes field, any document that is missing the field is not indexes;
    2. By contrast, non-sparse indexes contrain all documents in collection, and store null values for documents that do not contrain the indexes field;
    3. 语法:db.mycoll.ensureIndex(keypattern, {sparse:true});
    4. 稀疏索引与非稀疏索引的对比;
  6. hint:
    1. 查询优化器会选择最优的执行计划,而且第一次执行后的执行计划将会被保存;如果需要使用自己指定的查询方案的话可以使用hint;
    2. 语法:cursor.hint(index);
      1. db.mycoll.find().hint(“index_name”):通过指定索引名称来实现hint;
      2. db.mycoll.find().hint({key:value}):通过指定创建索引时的key的顺序来实现hint,可以之前通过db.mycoll.getIndexes()查看;
    3. 查看hint的性能:db.mycoll.find().hint(index).explain();
  7. 注意事项:
    1. MongoDB中的索引是大小写敏感的;
    2. 当更新对象时,只有在索引上的这些key发生变化才更新,所以提高了性能;当对象增长了或者移动时,所有的索引都必须更新,会很慢;
    3. 索引的信息会保存在system.indexes集合中,运行db.system.indexes.find()可以查看这些数据;
    4. 索引的字段的大小限制目前是800bytes,大于之后可以在这个字段上创建索引,但是该字段不会被索引;
    5. 如果数据集合比较小(4M),可以联合使用limit()和sort()函数而不需要创建索引来查询数据;
———————- 10w条测试数据 ———————-
db.index.remove()
for(var i = 0; i < 100000; i++){
     db.index.insert({name:”index”+i, age:i})
}
———————- 10w条测试数据 ———————-
———————- 稀疏索引与非稀疏索引的对比 ———————-
— 1.测试数据;
db.sparse.insert({name:”sparse1″, age:20})
db.sparse.insert({name:”sparse2″})
db.sparse.find()
— 2.在age列创建一个稀疏索引;
db.sparse.ensureIndex({age:1}, {name:”idx_sparse_age”, sparse:true})
db.sparse.getIndexes()
— 3.查看数据,稀疏索引中不包含列为null的文档,只有稀疏索引中的文档才会被返回;
db.sparse.find()
db.sparse.find().sort({age:1})
db.sparse.find({name:{$ne:0}})
— 4.删除稀疏索引,并创建一般的索引;
db.sparse.dropIndex(“idx_sparse_age”)
db.sparse.ensureIndex({age:1}, {name:”idx_sparse_age”})
db.sparse.getIndexes()
— 查看数据,非稀疏索引中包含了列为null的文档;
———————- 稀疏索引与非稀疏索引的对比 ———————-
标签: ,
目前还没有任何评论.