【问题标题】:How do I check if an index is being used如何检查是否正在使用索引
【发布时间】:2014-07-02 15:40:49
【问题描述】:

我有一个包含大量数据库、集合和索引的 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);
          }
        }
      }
    }
  }
}

【问题讨论】:

标签: mongodb


【解决方案1】:

对此最简单的解决方案是使用 MongoDB 3.2 中添加的 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

【讨论】:

【解决方案2】:

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

https://github.com/wfreeman/indexalizer

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

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

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

【讨论】:

  • 对许多目的有用的答案,不仅仅是这个问题。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-09
  • 2021-07-22
  • 2013-03-21
  • 2016-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多