跟踪“选择性”属性的问题是它需要不断地重新采样数据。此外,它假定每个选择性属性都将保留该属性,无论向查询提供什么值。
以下是一组可能属性的示例:
{ n:"lastName", v:"Kamsky" } vs. { n:"lastName", v:"Smith" }
{ n:"firstName", v:"Asya" } vs. { n:"firstName", v:"Jessica" }
{ n:"Age", v: 21 } vs. { n:"Age", v: 15 }
在前两个比较行中,姓氏和名字可以是非常有选择性的(当名字或姓氏很少见时)或不是特别有选择性的(当它在整个数据库中很常见时)。
在第三行,如果我们不知道数据库的内容是什么,我们无法判断“年龄”值中的任何一个是否具有选择性。如果您要查询的是大学生的集合,那么第二个值最终将具有极高的选择性,但如果是高中生,则第一个值将是高度选择性的值。
如果您的任何查询是不等式,那么我会说它们不会成为一个好的第一位置元素,除非其他元素都不是选择性的。
但是,您如何跟踪哪些是选择性的,哪些不是选择性的呢?
您可以执行以下操作来跟踪“统计信息”(可以这么说):
var X = 3; // assign a threshold equal to some number that's "too high" to scan
db.<collection>.aggregate(
{$unwind : "$records"},
{$group : {_id:{n:"$records.n",v:"$records.v"}, count:{$sum:1}}},
{$group : {_id:"$_id.n", totalDistinctValues:{$sum:1}, values:{$push:{value:"$_id.v", appears:"$count"}} } },
{$project : {_id:0, AttributeName:"$_id", totalDistinctValues:1, values:1}},
{$match : {"values.appears":{$not:{$gte: X }} }},
{$sort : {totalDistinctValues:1}},
{$limit : 10}
)
上述聚合将返回具有最独特(不同)值的十个属性。此外,每个文档都将包含可能值的列表以及它出现的次数。根据您的确切字段和可能的数据分布,有很大的调整空间 - 您当然可以将其保存到集合中进行查询,但我会简单地将其缓存在应用程序中,因为这不是有意义的坚持你描述的用例。
在我的小型测试集合中,返回的结果是这样的(我也有“雇主”字段,但有一半的记录列出了同一个雇主,因此将其删除):
[
{
"totalDistinctValues" : 5,
"AttributeName" : "firstName",
"values" : [
{
"value" : "Sheldon",
"appears" : 1
},
{
"value" : "Raj",
"appears" : 1
},
{
"value" : "Penny",
"appears" : 1
},
{
"value" : "Asya",
"appears" : 1
},
{
"value" : "John",
"appears" : 2
}
]
},
{
"totalDistinctValues" : 6,
"AttributeName" : "lastName",
"values" : [
{
"value" : "Kumar",
"appears" : 1
},
{
"value" : "Smith",
"appears" : 1
},
{
"value" : "Lane",
"appears" : 1
},
{
"value" : "Williams",
"appears" : 1
},
{
"value" : "Kamsky",
"appears" : 1
},
{
"value" : "Cooper",
"appears" : 1
}
]
},
{
"totalDistinctValues" : 6,
"AttributeName" : "Age",
"values" : [
{
"value" : 31,
"appears" : 1
},
{
"value" : 21,
"appears" : 1
},
{
"value" : 22,
"appears" : 1
},
{
"value" : 29,
"appears" : 1
},
{
"value" : 49,
"appears" : 1
},
{
"value" : 59,
"appears" : 1
}
]
}
]
底线:一旦您运行此聚合并查看数据中的真实分布,可能会发现某些属性自然具有选择性,并且总是(或经常)出现在查询中。把那些放在第一位。否则,请使用统计信息将更具选择性的属性首先动态放置,然后对https://jira.mongodb.org/browse/SERVER-2348进行投票,它正在跟踪此类查询的索引使用改进。