如何检测 "useless" 个索引?
How can one detect "useless" indexes?
我有一个包含很多索引的 MongoDB 集合。
删除很少使用的索引会带来什么好处吗?
有什么方法或工具可以告诉我(用数字表示)索引的使用频率吗?
编辑: 我使用的是版本 2.6.4
EDIT2: 我现在使用的是版本 3.0.3
好的,这就是我要做的。
首先,您需要一个特定集合的所有索引的列表(这将逐个集合完成)。假设我们正在监视 user
集合以查看哪些索引无用。
所以我 运行 a db.user.getIndexes()
这导致 JSON 的可解析输出(您可以从客户端通过 command()
运行以及与脚本集成)。
现在你有了一个索引列表。这只是了解哪些查询使用哪些索引的情况。如果那个索引根本没有命中,你就知道它没用了。
现在,您需要 运行 从该输出中使用 explain()
的每个查询,您可以判断使用了哪个索引并将其与从 getIndexes()
.[=24 获得的索引相匹配=]
所以这是一个示例输出:
> db.user.find({religion:1}).explain()
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "meetapp.user",
"indexFilterSet" : false,
"parsedQuery" : {
"religion" : {
"$eq" : 1
}
},
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"religion" : NumberLong(1)
},
"indexName" : "religion_1",
"isMultiKey" : false,
"direction" : "forward",
"indexBounds" : {
"religion" : [
"[1.0, 1.0]"
]
}
}
},
"rejectedPlans" : [ ]
},
"serverInfo" : {
"host" : "ip-172-30-0-35",
"port" : 27017,
"version" : "3.0.0",
"gitVersion" : "a841fd6394365954886924a35076691b4d149168"
},
"ok" : 1
}
queryPlanner
字段将使用一组规则,您将需要发现并编写它们,但第一个很简单。
如您所见:获胜计划(在 winningPlan
中)是一个(可能是多个记住,这些东西你需要编写代码)IXSCAN
(索引扫描)和使用的索引的键模式是:
"keyPattern" : {
"religion" : NumberLong(1)
},
很好,现在我们可以匹配 getIndexes()
的键输出:
{
"v" : 1,
"key" : {
"religion" : NumberLong(1)
},
"name" : "religion_1",
"ns" : "meetapp.user"
},
to 告诉我们 religion
索引不是无用的,实际上已经被使用了。
不幸的是,这是我能看到的最好的方式。以前 MongoDB 有一个索引统计数据,用于记录索引被命中的次数,但似乎数据已被删除。
所以您只需为您拥有的每个集合冲洗并重复此过程,直到删除无用的索引。
当然,另一种方法是删除所有索引,然后在测试查询时重新添加索引。如果您确实需要在生产中执行此操作,那可能会很糟糕。
附带说明:解决此问题的最佳方法是完全不使用它。
我通过在活动记录中使用索引功能使这对我来说更容易。每隔一段时间,我 运行(来自 PHP)类似的东西:./yii index/rebuild
它基本上遍历我的活动记录模型并检测我不再使用并已从我的应用程序中删除的索引并依次移除它们。当然,它会创建新索引。
我有一个包含很多索引的 MongoDB 集合。
删除很少使用的索引会带来什么好处吗?
有什么方法或工具可以告诉我(用数字表示)索引的使用频率吗?
编辑: 我使用的是版本 2.6.4
EDIT2: 我现在使用的是版本 3.0.3
好的,这就是我要做的。
首先,您需要一个特定集合的所有索引的列表(这将逐个集合完成)。假设我们正在监视 user
集合以查看哪些索引无用。
所以我 运行 a db.user.getIndexes()
这导致 JSON 的可解析输出(您可以从客户端通过 command()
运行以及与脚本集成)。
现在你有了一个索引列表。这只是了解哪些查询使用哪些索引的情况。如果那个索引根本没有命中,你就知道它没用了。
现在,您需要 运行 从该输出中使用 explain()
的每个查询,您可以判断使用了哪个索引并将其与从 getIndexes()
.[=24 获得的索引相匹配=]
所以这是一个示例输出:
> db.user.find({religion:1}).explain()
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "meetapp.user",
"indexFilterSet" : false,
"parsedQuery" : {
"religion" : {
"$eq" : 1
}
},
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"religion" : NumberLong(1)
},
"indexName" : "religion_1",
"isMultiKey" : false,
"direction" : "forward",
"indexBounds" : {
"religion" : [
"[1.0, 1.0]"
]
}
}
},
"rejectedPlans" : [ ]
},
"serverInfo" : {
"host" : "ip-172-30-0-35",
"port" : 27017,
"version" : "3.0.0",
"gitVersion" : "a841fd6394365954886924a35076691b4d149168"
},
"ok" : 1
}
queryPlanner
字段将使用一组规则,您将需要发现并编写它们,但第一个很简单。
如您所见:获胜计划(在 winningPlan
中)是一个(可能是多个记住,这些东西你需要编写代码)IXSCAN
(索引扫描)和使用的索引的键模式是:
"keyPattern" : {
"religion" : NumberLong(1)
},
很好,现在我们可以匹配 getIndexes()
的键输出:
{
"v" : 1,
"key" : {
"religion" : NumberLong(1)
},
"name" : "religion_1",
"ns" : "meetapp.user"
},
to 告诉我们 religion
索引不是无用的,实际上已经被使用了。
不幸的是,这是我能看到的最好的方式。以前 MongoDB 有一个索引统计数据,用于记录索引被命中的次数,但似乎数据已被删除。
所以您只需为您拥有的每个集合冲洗并重复此过程,直到删除无用的索引。
当然,另一种方法是删除所有索引,然后在测试查询时重新添加索引。如果您确实需要在生产中执行此操作,那可能会很糟糕。
附带说明:解决此问题的最佳方法是完全不使用它。
我通过在活动记录中使用索引功能使这对我来说更容易。每隔一段时间,我 运行(来自 PHP)类似的东西:./yii index/rebuild
它基本上遍历我的活动记录模型并检测我不再使用并已从我的应用程序中删除的索引并依次移除它们。当然,它会创建新索引。