Mongo<=2.0.1 $and对索引的使用和$and如何工作
2012-02-01 13:59
323 查看
Mongo<=2.0.1 $and对索引的使用和$and如何工作
.Mongo:$and索引trap下面是一些细节问题。自己在使用过程中遇到的。
[cpp] view plaincopyprint?
for (var i=0; i<1000000; i++) {
db.good.insert({"x":[i, i+1, i+2, i+3, i+4]});
}
向good中插入100W数据。
然后给x建立索引
ensureIndex({"x":1})
分别进行下面的搜索:
[cpp] view plaincopyprint?
db.good.find({"x":{"$gt":100}}).explain()
->
{
"cursor" : "BtreeCursor x_1",
"nscanned" : 4999505,
"nscannedObjects" : 4999505,
"n" : 999903
...
}
db.good.find({"x":{"$lt":100}})
->
{
"cursor" : "BtreeCursor x_1",
"nscanned" : 490,
"nscannedObjects" : 490,
"n" : 100
...
}
db.good.find({"$and":[{"x":{"$gt":100}}]}) //为什么没利用索引?? (include gte)
->
{
"cursor" : "BasicCursor",
"nscanned" : 1000000,
"nscannedObjects" : 1000000,
"n" : 999903
...
}
db.good.find({"$and":[{"x":{"$lt":100}}]}) (include lte)
->
{
"cursor" : "BtreeCursor x_1",
"nscanned" : 490,
"nscannedObjects" : 490,
"n" : 100
...
}
db.good.find({"$and":[{"x":101},{"x":{"$gt":100}}]}) // So, gt/gte操作不建议放在第一个
->
{
"cursor" : "BtreeCursor x_1",
"nscanned" : 5,
"nscannedObjects" : 5,
"n" : 5
...
}
2011.11.28 经证实 的确是mongobug: 详文:https://jira.mongodb.org/browse/SERVER-4180
While bumping from 1.8 to mongo 2.0.1, we noticed some query optimization seemed not to work anymore. After some laborious digging in our data, we found out a single document showing the issue.
Please open the attached .tgz. The tc.sh script will restore the document in a core.picture_set_pictures collection on a localhost:27017 mongo, setup an index, and explain a range query on a date embedded in a array of objects. The relevant section of the output shows.
"indexBounds" : { "votes.created_at" : [ [ ISODate("2010-10-31T13:37:20Z"), ISODate("292278995-01--2147483647T07:12:56.808Z") ] ] }
The upper bound is completely aberrant, and as far as I can tell, nothing in the document justifies such a value. As a consequence, on the real database, this will scan half of the table for every request. On the contrary, 1.8.3 was showing the right upper bound. Please also note that as far as we can tell, our collections have other instances of documents raising the problem (that is, a collection with just this document will exhibit the issue, but just removing the doc from the collection is not enough for the issue to disappear).
.....................>>另外关于自己对$and的整理:
[cpp] view plaincopyprint?
for (var i=0; i<1000000; i++) {
db.good.insert({"x":[i, i+1, i+2, i+3, i+4]})
}
db.good.find({"x":{"$gt":4,"$lt":5}})
{ "_id" : ObjectId("4ecf56d1aef0cdc1103012e4"), "x" : [ 1, 2, 3, 4, 5 ] }
{ "_id" : ObjectId("4ecf56d1aef0cdc1103012e5"), "x" : [ 2, 3, 4, 5, 6 ] }
{ "_id" : ObjectId("4ecf56d1aef0cdc1103012e6"), "x" : [ 3, 4, 5, 6, 7 ] }
{ "_id" : ObjectId("4ecf56d1aef0cdc1103012e7"), "x" : [ 4, 5, 6, 7, 8 ] }
这种操作有点类似$and操作。下面会说,但不是取交集的操作。尤其要注意。
如果需要 and关系 可以使用 $elemMatch
> db.good.find({"x":{"$elemMatch":{"$gt":4, "$lt":5}}})
>
db中没有符合 >4 and <5的数据 所以就没出来。
把lt改成lte
> db.good.find({"x":{"$elemMatch":{"$gt":4, "$lte":5}}})
{ "_id" : ObjectId("4ecf56d1aef0cdc1103012e4"), "x" : [ 1, 2, 3, 4, 5 ] }
{ "_id" : ObjectId("4ecf56d1aef0cdc1103012e5"), "x" : [ 2, 3, 4, 5, 6 ] }
{ "_id" : ObjectId("4ecf56d1aef0cdc1103012e6"), "x" : [ 3, 4, 5, 6, 7 ] }
{ "_id" : ObjectId("4ecf56d1aef0cdc1103012e7"), "x" : [ 4, 5, 6, 7, 8 ] }
{ "_id" : ObjectId("4ecf56d1aef0cdc1103012e8"), "x" : [ 5, 6, 7, 8, 9 ] }
我们再来看下 2.0版本出来的 $and 操作是否可以取出正确的结果。
> db.good.find({"$and":[{"x":{"$gt":4}}, {"x":{"$lt":5}}]})
{ "_id" : ObjectId("4ecf56d1aef0cdc1103012e4"), "x" : [ 1, 2, 3, 4, 5 ] }
{ "_id" : ObjectId("4ecf56d1aef0cdc1103012e5"), "x" : [ 2, 3, 4, 5, 6 ] }
{ "_id" : ObjectId("4ecf56d1aef0cdc1103012e6"), "x" : [ 3, 4, 5, 6, 7 ] }
{ "_id" : ObjectId("4ecf56d1aef0cdc1103012e7"), "x" : [ 4, 5, 6, 7, 8 ] }
结果也不是交集。而是匹配了 document中是否有x>4的值而且也必须有x<5的值。
$and和$elemMatch区别也就在与区间 即:1<x<5 按照$and理解:1<x and x<5 这里把1<x把5考虑进去了,同理x<5把1<x考虑进去了。
$and和不加$and的区别在于:
> db.good.find({"x":{"$lt":5,"$gt":1}})
{ "_id" : ObjectId("4ed061427ecbeebf00e65625"), "x" : [ 0, 1, 2, 3, 4 ] }
{ "_id" : ObjectId("4ed061427ecbeebf00e65626"), "x" : [ 1, 2, 3, 4, 5 ] }
{ "_id" : ObjectId("4ed061427ecbeebf00e65627"), "x" : [ 2, 3, 4, 5, 6 ] }
{ "_id" : ObjectId("4ed061427ecbeebf00e65628"), "x" : [ 3, 4, 5, 6, 7 ] }
{ "_id" : ObjectId("4ed061427ecbeebf00e65629"), "x" : [ 4, 5, 6, 7, 8 ] }
> db.good.find({"x":{"$lt":5}, "x":{"$gt":1}})
{ "_id" : ObjectId("4ed061427ecbeebf00e65625"), "x" : [ 0, 1, 2, 3, 4 ] }
{ "_id" : ObjectId("4ed061427ecbeebf00e65626"), "x" : [ 1, 2, 3, 4, 5 ] }
{ "_id" : ObjectId("4ed061427ecbeebf00e65627"), "x" : [ 2, 3, 4, 5, 6 ] }
{ "_id" : ObjectId("4ed061427ecbeebf00e65628"), "x" : [ 3, 4, 5, 6, 7 ] }
{ "_id" : ObjectId("4ed061427ecbeebf00e65629"), "x" : [ 4, 5, 6, 7, 8 ] }
{ "_id" : ObjectId("4ed061427ecbeebf00e6562a"), "x" : [ 5, 6, 7, 8, 9 ] }
{ "_id" : ObjectId("4ed061427ecbeebf00e6562b"), "x" : [ 6, 7, 8, 9, 10 ] }
{ "_id" : ObjectId("4ed061427ecbeebf00e6562c"), "x" : [ 7, 8, 9, 10, 11 ] }
{ "_id" : ObjectId("4ed061427ecbeebf00e6562d"), "x" : [ 8, 9, 10, 11, 12 ] }
{ "_id" : ObjectId("4ed061427ecbeebf00e6562e"), "x" : [ 9, 10, 11, 12, 13 ] }
{ "_id" : ObjectId("4ed061427ecbeebf00e6562f"), "x" : [ 10, 11, 12, 13, 14 ] }
{ "_id" : ObjectId("4ed061427ecbeebf00e65630"), "x" : [ 11, 12, 13, 14, 15 ] }
{ "_id" : ObjectId("4ed061427ecbeebf00e65631"), "x" : [ 12, 13, 14, 15, 16 ] }
{ "_id" : ObjectId("4ed061427ecbeebf00e65632"), "x" : [ 13, 14, 15, 16, 17 ] }
{ "_id" : ObjectId("4ed061427ecbeebf00e65633"), "x" : [ 14, 15, 16, 17, 18 ] }
{ "_id" : ObjectId("4ed061427ecbeebf00e65634"), "x" : [ 15, 16, 17, 18, 19 ] }
{ "_id" : ObjectId("4ed061427ecbeebf00e65635"), "x" : [ 16, 17, 18, 19, 20 ] }
{ "_id" : ObjectId("4ed061427ecbeebf00e65636"), "x" : [ 17, 18, 19, 20, 21 ] }
{ "_id" : ObjectId("4ed061427ecbeebf00e65637"), "x" : [ 18, 19, 20, 21, 22 ] }
{ "_id" : ObjectId("4ed061427ecbeebf00e65638"), "x" : [ 19, 20, 21, 22, 23 ] }
当这样使用的时候就需要$and了
相关文章推荐
- Mongo<=2.0.1 $and索引trap bug? yep, bug!!
- 如何使用<Beginning ASP.NET 3.5 in C# and VB>书中的示例代码
- ubuntu使用apt-get --如何解决Please verify ICU install prefix and make sure icu-config works.
- OpenCV3如何使用SIFT和SURF Where did SIFT and SURF go in OpenCV 3?
- 如何理解并正确使用MySQL索引
- wireshark的使用教程--用实践的方式帮助我们理解TCP/IP中的各个协议是如何工作的
- 数据仓库中如何使用索引
- 如何使用u 4000 nity3d进行地形编辑/百分之一系列<1>
- 如何调试 SDWebImage,使用前的准备工作
- 如何获得SQL Server索引使用情况
- 如何使用 HP Backup and Recovery Manager 备份个人文件和文件夹
- 如何理解并正确使用MySql索引
- 索引的使用跟查询的and的前后顺序没有关系
- 如何监控oracle的索引是否使用
- html第三天 如何使用<table>制作一个网页
- wireshark的使用教程--用实践的方式帮助我们理解TCP/IP中的各个协议是如何工作的
- 如何直接使用Android internal and hidden APIs
- RBO如何确定使用索引的顺序
- 如何知道SQL SERVER索引的使用情况
- 如何使用redis缓存加索引处理数据库百万级并发