如何检查是否正在使用索引

时间:2014-07-02 15:40:50

标签: mongodb

我有一个mongodb副本集,其中包含大量数据库,集合和数据库。索引。

我们做了很多重构和优化,当然,我有很多来自消费者的“创意查询”。

我想清理未使用的索引。只是想节省一些空间。

如何检查是否正在使用索引?我可以负担得起索引索引并删除未使用的索引。

在所有可能的查询中运行“解释”不是一个选项:)

编辑:基于接受的答案的解决方案

脚本被窃听了。我不是一个JavaScript专家,但我把更正后的脚本。我希望对某人有用:

DB.prototype.indexStats = function() {
  var queries = [];
  var collections = db.getCollectionNames();

  var findQuery = function(q) {
    for(entryIdx in queries) {
      if(q == queries[entryIdx].query) {
        return entryIdx;
      }
    }
    return -1;
  }

  for(cIdx in collections) {
    var cName = collections[cIdx];
    var nsName = db.getName()+"."+cName;
    if(cName.indexOf("system") == -1) {
      var i = 1;
      var count = db.system.profile.count({ns:nsName});
      print('scanning profile {ns:"'+nsName+'"} with '+count+' records... this could take a while...');
      db.system.profile.find({ns:nsName}).addOption(16).batchSize(10000).forEach(function(profileDoc) {           
        if(profileDoc.query && !profileDoc.query["$explain"]) { 
          var qIdx = findQuery(profileDoc.query);
          if(qIdx == -1 && profileDoc.query["query"] ) {
            var size = queries.push({query:profileDoc.query, count:1, index:""});                   
            var explain = db[cName].find(queries[size-1].query).explain();
            if(profileDoc.query && profileDoc.query["query"]) {
              queries[size-1].sort = profileDoc.query["orderby"];
              if(queries[size-1].sort) {
                explain = db[cName].find(queries[size-1].query.query).sort(queries[size-1].sort).explain();
              }
            }
            queries[size-1].cursor = explain.cursor;
            queries[size-1].millis = explain.millis;
            queries[size-1].nscanned = explain.nscanned;
            queries[size-1].n = explain.n;
            queries[size-1].scanAndOrder = explain.scanAndOrder ? true : false;
            if(explain.cursor && explain.cursor != "BasicCursor") {
              queries[size-1].index = explain.cursor.split(" ")[1];             
            } else {
              print('warning, no index for query {ns:"'+nsName+'"}: ');
              printjson(profileDoc.query);
              print('... millis: ' + queries[size-1].millis);
              print('... nscanned/n: ' + queries[size-1].nscanned + '/' + queries[size-1].n);
              print('... scanAndOrder: ' + queries[size-1].scanAndOrder);
            }
          } else if ( qIdx != -1 ) {
            queries[qIdx].count++;
          }
        }
      });
    }
  }

  for(cIdx in collections) {
    var cName = collections[cIdx];
    if(cName.indexOf("system") == -1) {
      print('checking for unused indexes in: ' + cName);
      for(iIdx in db[cName].getIndexes()) {
        var iName = db[cName].getIndexes()[iIdx].name;
        if(iName.indexOf("system") == -1) {
          var stats = db[cName].stats();
          var found = false;
          for(qIdx in queries) {
            if(queries[qIdx].index == iName) {
              found = true;
              break;
            }
          }
          if(!found) {
            print('this index is not being used: ');
            printjson(iName);
          }
        }
      }
    }
  }
}

2 个答案:

答案 0 :(得分:38)

最简单的解决方案是使用mongodb内置$indexStats

使用Mongo控制台运行 -

db.collection.aggregate([ { $indexStats: { } } ])

使用PyMongo -

from pymongo import MongoClient
collection = MongoClient()[db_name][collection_name]
index_stats = collection.aggregate([{'$indexStats':{}}])

for index_info in index_stats:
    print index_info

道歉重新打开旧问题。这显示在谷歌搜索的第一页上,唯一的答案是使用一段未维护的代码。

答案 1 :(得分:11)

Github上有一个非常酷的脚本你应该看看:

https://github.com/wfreeman/indexalizer

基本上它涉及打开数据库的分析,然后它将使用分析器收集的数据来驱动explain()调用。然后它会告诉您哪些索引未被使用以及哪些查询未使用索引。很漂亮。

有关mongoDB数据库分析的更多信息:

http://docs.mongodb.org/manual/reference/database-profiler/