【知识小课堂】4 之 索引
来源:互联网 发布:鸟哥笔记 知乎 编辑:程序博客网 时间:2024/06/10 17:19
索引类型
mongoDB 的索引在存储结构都是一样的,但是根据不同的应用需求,还是分成了:唯一索引,稀疏索引,复合索引
1.唯一索引
MONGODB 在默认建立文档时,都会自动添加一个:“_id” 字段,而此字段默认建立唯一索引;
如果我们要使一个键值在文档中唯一,我们就要在此字段建立一个唯一索引,语法如下:
db.users.ensureIndex({account:1},{unique:true})
和其它数据库一样,唯一索引,此字段是允许值为NULL 的,但只允许有一条。
当然,我们也可以在多个字段中建立一个唯一索引:
db.users.ensureIndex({mobile:1,email:1},{unique:true})
2.稀疏索引
有这样一个问题:
如果某个字段,如果它存在,那么必须是唯一,因为 会把null当做值,如果定义了唯一索引,那么此字段只能存在一个null值的记录。
这时我们可以使用以下方法定义这个索引:
db.user.ensureIndex({email:1},{“unique”:true,”sparese”:true})
当然,上面是为了方便理解而举的一个例子。其实 【稀疏索引】并不是必须是唯一索引。
db.user.ensureIndex({email:1},{”sparese”:true})
我们也看一个 稀疏索引查询
> db.foo.find(){ "_id" : 0 }{ "_id" : 1, "x" : 1 }{ "_id" : 2, "x" : 2 }{ "_id" : 3, "x" : 3 }> db.foo.find({x:{$ne:2}}){ "_id" : 0 }{ "_id" : 1, "x" : 1 }{ "_id" : 3, "x" : 3 }
在文档的x 键建立一个 [稀疏索引]
> db.foo.ensureIndex({x:1},{sparse:true})> db.foo.getIndexes()[{"v" : 1,"key" : {"_id" : 1},"ns" : "test.foo","name" : "_id_"},{"v" : 1,"key" : {"x" : 1},"ns" : "test.foo","name" : "x_1","sparse" : true}]
完成后,我们再来查询看看:
> db.foo.find({x:{$ne:2}}){ "_id" : 1, "x" : 1 }{ "_id" : 3, "x" : 3 }>
看到,这时查询结果,已排除了 没有键 X 的文档 _id:0 了。
就是因为在建立索引时,“_id”=0 的文档,不会包含在索引中。
当然,如果你需要查询到 那些不包含 “x” 的 文档。你可以使用 hint() 来强制全表或其它索引搜索。
比如我下面的代码:
> db.foo.find({x:{$ne:2}}).hint({"_id":1}){ "_id" : 0 }{ "_id" : 1, "x" : 1 }{ "_id" : 3, "x" : 3 }
全表索引:
> db.foo.find({x:{$ne:2}}).hint({$natural:1}){ "_id" : 0 }{ "_id" : 1, "x" : 1 }{ "_id" : 3, "x" : 3 }>
3.复合索引
上面这段话,在mongodb 也有效。
> db.order_detail.find(){ "_id" : 1, "cust_id" : 1, "order_id" : 1, "prod_id" : 1 }{ "_id" : 2, "cust_id" : 1, "order_id" : 1, "prod_id" : 2 }{ "_id" : 3, "cust_id" : 2, "order_id" : 2, "prod_id" : 2 }{ "_id" : 4, "cust_id" : 3, "order_id" : 2, "prod_id" : 1 }{ "_id" : 5, "cust_id" : 3, "order_id" : 3, "prod_id" : 3 }> db.order_detail.ensureIndex({cust_id:1,order_id:1})
> db.order_detail.getIndexes()[{"v" : 1,"key" : {"_id" : 1},"ns" : "test.order_detail","name" : "_id_"},{"v" : 1,"key" : {"cust_id" : 1,"order_id" : 1},"ns" : "test.order_detail","name" : "cust_id_1_order_id_1"}]
上面文档在建立完成复合索引后,我们来查询一下数据,并看看执行计划:
> db.order_detail.find({order_id:1}).explain(){"cursor" : "BasicCursor","isMultiKey" : false,"n" : 2,"nscannedObjects" : 5,"nscanned" : 5,"nscannedObjectsAllPlans" : 5,"nscannedAllPlans" : 5,"scanAndOrder" : false,"indexOnly" : false,"nYields" : 0,"nChunkSkips" : 0,"millis" : 0,"indexBounds" : {},"server" : "localhost.localdomain:27017"}
我指定了一个组合索引中后面一个字段进行查询可以看到,确实没用到索引
再来看看下面代码:
> db.order_detail.find({order_id:1}).sort({cust_id:1}).explain(){"cursor" : "BtreeCursor cust_id_1_order_id_1","isMultiKey" : false,"n" : 2,"nscannedObjects" : 2,"nscanned" : 4,"nscannedObjectsAllPlans" : 4,"nscannedAllPlans" : 6,"scanAndOrder" : false,"indexOnly" : false,"nYields" : 0,"nChunkSkips" : 0,"millis" : 0,"indexBounds" : {"cust_id" : [[{"$minElement" : 1},{"$maxElement" : 1}]],"order_id" : [[1,1]]},"server" : "localhost.localdomain:27017"}>
我指定了一个组合索引中 后面一个字段进行查询,但我增加了一个第一个字段的排序。这时可以看到,它用到索引了。
看来还是有办法解决复合索引的缺陷的。
还有办法:
>db.order_detail.find({order_id:1}).hint({cust_id:1,order_id:1}).explain(){"cursor" : "BtreeCursor cust_id_1_order_id_1","isMultiKey" : false,"n" : 2,"nscannedObjects" : 2,"nscanned" : 4,"nscannedObjectsAllPlans" : 2,"nscannedAllPlans" : 4,"scanAndOrder" : false,"indexOnly" : false,"nYields" : 0,"nChunkSkips" : 0,"millis" : 0,"indexBounds" : {"cust_id" : [[{"$minElement" : 1},{"$maxElement" : 1}]],"order_id" : [[1,1]]},"server" : "localhost.localdomain:27017"}>
我指定了一个组合索引中后面一个字段进行查询,但我使用了指定索引进行查询。
这时看到,查询也用到索引了。
但这时因为第一个字段为空值,在进行索引检索时,肯定会搜索更多的数据。
有可能是 fullindexsearch.
但总比全表索搜好吧。
- 【知识小课堂】4 之 索引
- 【知识小课堂】mongodb 之 特殊集合及索引
- 【知识小课堂】 mongodb 之 objectId
- 【知识小课堂】 之 聚合函数
- 【知识小课堂】mongodb 之 查询关键词使用
- java 课堂小知识总结
- java 课堂小知识总结
- mysql索引小知识
- C语言知识学习课堂小笔记
- 【知识小课堂】 mongodb 之字段中的【 数组】、【内嵌文档】
- 数据库之索引知识
- 知识课堂与生命课堂
- 数学小知识&总结索引(持续更新)
- 课堂知识总结
- 课堂知识总结
- 课堂知识总结
- 课堂知识整理
- andriod之String小知识
- JavaSE实战项目--愤怒的小鸟拼图
- 杭电2033 结构体的应用,注意大于60时需要进一位的
- android源码编译前期准备
- vlc 插件加载模拟程序
- Spring + mybatis整合实例应用
- 【知识小课堂】4 之 索引
- Python入门(二,基础)
- 鸟哥的Linux私房菜基础学习篇(第二版)第六章课后习题与答案
- Android中获取联系人时的注意事项
- Android 深入理解View
- 套接字编程(VC_Win32)
- 结束,也是起点。
- 使用Director::getInstance()->pause()需谨慎
- Java命令行运行参数说明大全