我有一个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);
}
}
}
}
}
}
答案 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数据库分析的更多信息: