MongoDB 学习五:索引
这章我们介绍MongoDB的索引,用来优化查询。
索引介绍
数据库索引有些类似书的目录。
一个查询如果没有使用索引被称为表扫描,意思是它必须像阅读整本书那样去获取一个查询结果。一般来说,我们应尽量避免这种情况,
因为它是非常慢的。
举个例子,我们创建一个百万条数据的collection:
for(i=0;i<1000000;i++){
     db.users.insert({
          "i":i,
          "username":"user" + i,
          "age":Math.floor(Math.random()*120),
          "created":new Date()
   })
}
假如我们查找这个collection,我们可以使用explain()来查看详细的查询信息。例如:
db.users.find({username:"user101"}).explain();
返回
{
        "cursor" : "BasicCursor",
        "isMultiKey" : false,
        "n" : 1,
        "nscannedObjects" : 1000000,
        "nscanned" : 1000000,
        "nscannedObjectsAllPlans" : 1000000,
        "nscannedAllPlans" : 1000000,
        "scanAndOrder" : false,
        "indexOnly" : false,
        "nYields" : 7812,
        "nChunkSkips" : 0,
        "millis" : 521,
        "server" : "Colin_xu:27017",
        "filterSet" : false
}
上述信息要点:
"cursor":"BasicCursor"说明查询没有使用索引
"nscanned":1000000 代表查询了多少文档
"n":1 代表返回文档的数量
"millis":521 代表数据库执行查询的时间(毫秒)
这时我们加上索引:
db.user.ensureIndex({"username":1})
这时再查询的返回结果:
{
        "cursor" : "BtreeCursor username_1",
        "isMultiKey" : false,
        "n" : 1,
        "nscannedObjects" : 1,
        "nscanned" : 1,
        "nscannedObjectsAllPlans" : 1,
        "nscannedAllPlans" : 1,
        "scanAndOrder" : false,
        "indexOnly" : false,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "millis" : 47,
        "indexBounds" : {
                "username" : [
                        [
                                "user101",
                                "user101"
                        ]
                ]
        },
        "server" : "Colin_xu:27017",
        "filterSet" : false
}
这时我们看看两次结果的misllis,差距显而易见。
复合索引
当查询中排序中仅使用一个键时,可以对该键建立索引,以提高查询速度。然而,对于其他查询可能没有帮助,即便是查询包含了被索引的键。
所以,一定要创建查询中用到所有键的索引。
索引名称
集合中的每个索引都有一个字符串类型的名字,来唯一标识索引,服务器通过这个名字来删除或者操作索引。
默认情况下,索引名类似keyname1_dir1_keyname2_dir2_..._keynameN_dirN这种形式,其中keynameX代表索引的键,
dirX代表索引的方向(1或者-1)。要是索引的键特别多,这样命名就略显愚笨,不过还好可以通过ensureIndex的选项来自定义名字。
db.foo.ensureIndex({"a":1,"b":1,"c":1,...,"z":1},{"name":"alphabet"})
索引名有字符个数的限制,所以特别复杂的索引在创建时一定要用自定义名字。
唯一索引
唯一索引可以确保集合的每一个文档的指定键都有唯一值。例如,如果想保证文档的"username"键都有不一样的值,创建一个唯一索引就好了:
db.users.ensureIndex({"username":1},{"unique":true});
消除重复
当为已有的集合创建索引,可能有些值已经有重复了。若是真的发生这种情况,那么索引的创建就是失败。有些时候,可能希望将所有包含重复值的文档都删掉。
dropDups选项就可以保留发现的第一个文档,而删除接下来的有重复值的文档:
db.people.ensureIndex({"username":1},{"unique":true,"dropDups":true})
地理空间索引
还有一种查询变得越来越流行(尤其是随着移动设备的出现);找到离当前位置最近的N个场所。MongoDB为坐标平面查询提供了专门的索引,称为地理空间索引。
假设要找到给定经纬度周围最近的咖啡馆,就需要创建一个专门的索引来提高这种查询的效率,这是因为这种查询需要搜索两个维度。地理空间索引同样可以由ensureIndex来创建,
只不过参数不是1,而是"2d";
db.map.ensureIndex({"gps":"2d"})
"gps"键的值必须是某种形式的一对值:一个包含两个元素的数组或是包含两个键的内嵌文档。下面这些都是有效的:
{"gps":[0,100]};
{"gps":{"x":-30,"y":30}};
{"gps":{"latitude":-180,"longitude":180}};
至于键名可以随意。
地理空间查询以两种方式进行,即普通查询或者使用数据库命令。find的方式与一般的查询差别不大,只不过用了"$near"。需要两个目标值的数组作为参数:
db.map.find({"gps":{"$near":[40,-73]}})
这会按照离点(40,-73)由近及远的方式将map集合的所有文档都返回。在没有指定limit的值时,默认是100个文档。
也可以使用geoNear来完成相同操作。
db.runCommond({"geoNear”:"map","near":[40,-73]})
geoNear还会返回每个文档到查询点的距离,这个距离是以你插入的数据为单位的,如果按照经纬度的角度插入,则距离就是经纬度。
find和"$near"的组合不会给出距离,但若结果大于4M,这是唯一的选择。
MongoDB 学习五:索引的更多相关文章
- MongoDB学习笔记~索引提高查询效率
		回到目录 索引这个东西大家不会陌生,只要接触到稍微大一点的数据,都会用到这东西,它可以提升查询的速度,相当代价就是占用了更多的存储空间,这也是正常的,符合“能量守恒定理”,哈哈!今天说的是MongoD ... 
- MongoDB学习笔记(索引)
		一.索引基础: MongoDB的索引几乎与传统的关系型数据库一模一样,这其中也包括一些基本的优化技巧.下面是创建索引的命令: > db.test.ensureIndex({" ... 
- MongoDB学习笔记(索引)(转)
		一.索引基础: MongoDB的索引几乎与传统的关系型数据库一模一样,这其中也包括一些基本的优化技巧.下面是创建索引的命令: > db.test.ensureIndex({" ... 
- MongoDB学习笔记——索引管理
		索引 索引能够提升查询的效率.没有索引,MongoDB必须扫描集合中的所有文档,才能找到匹配查询语句的文档. 索引是一种特殊的数据结构,将一小块数据集保存为容易遍历的形式.索引能够存储某种特殊字段或字 ... 
- [转载]MongoDB学习 (五):查询操作符(Query Operators).1st
		本文地址:http://www.cnblogs.com/egger/archive/2013/05/04/3059374.html 欢迎转载 ,请保留此链接๑•́ ₃•̀๑! 查询操作符(Quer ... 
- mongodb学习(六)索引
		准备工作: 先插入100万条数据 for(i=0;i<=1000000;i++){ db.users.insert({ "i":i, "username" ... 
- MongoDB学习day08--Mongoose索引、Mongoose内置方法、扩展Mongoose Model的静态方法和实例方法
		一.Mongoose索引 索引是对数据库表中一列或多列的值进行排序的一种结构, 可以让我们查询数据库变得更快. MongoDB 的索引几乎与传统的关系型数据库一模一样, 这其中也包括一些基本的查询优化 ... 
- mongodb学习(五) 查询
		1. 按条件查询: db.users.find({"name":"MM1"}) 2.find的第二个参数可以指定要返回的字段:这里1 表示要显示的字段,0 表示 ... 
- MongoDB学习笔记系列
		回到占占推荐博客索引 该来的总会来的,Ef,Redis,MVC甚至Sqlserver都有了自己的系列,MongoDB没有理由不去整理一下,这个系列都是平时在项目开发时总结出来的,希望可以为各位一些帮助 ... 
随机推荐
- Linux 之 用户及用户组
			用户及用户组 参考教程:[千峰教育] 命令: whoami: 作用:查看当前登录的用户. 格式:whoami /etc/passwd: 说明:该文件存放了系统中所有的用户,每一行的每一列如下: 用户名 ... 
- AC日记——绿色通道 codevs 3342
			3342 绿色通道 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 黄金 Gold 题解 查看运行结果 题目描述 Description <思远高考绿色通道&g ... 
- Java原来如此-随机数
			在Java中,生成随机数有两种方法.1是使用Random类.2是使用Math类中的random方法. 我们现在做个例子,比如生成20个0到10之间的随机数. 1.使用Random类的nextInt(n ... 
- Java 网络通信【01】TCP
			不积跬步,无以至千里:不积小流,无以成江海.——<荀子劝学> JAVA中设计网络编程模式的主要有TCP和UDP两种. TCP是属于即时通信,点对点连接进行通信. UDP是通过数据包来进行通 ... 
- GPP加密破解工具gpp-decrypt
			GPP加密破解工具gpp-decrypt GPP是Group Policy Preferences(组策略首选项)的缩写,这是一个组策略实施工具.通过该工具,网络管理员可以实现更多的网络管理,如驱 ... 
- java excel导出(基于注解)
			小白,做日志只是为了方便自己查看,能帮到别人当然更好,不喜勿喷. 上代码 依赖: <dependency> <groupId>org.apache.poi</groupI ... 
- Maven依赖机制理解
			假设一个项目需要用到日志组件Log4j,那么有如下方式添加这个组件. 一.传统方式: 1.访问官网https://logging.apache.org/log4j/2.x/download.html, ... 
- U-boot for Tiny4412
			我的开发板型号: Tiny4412ADK + S700 4GB Flash 1. Build uboot a) 安装好toolchain (arm-linux-gcc-4.5.1-v6-vfp-201 ... 
- Code Sign error: a valid provisioning profile matching the application's Identifier 'com. sensoSource.VoiceRecorder' could not be found
			如果不是com. sensoSource.VoiceRecorder,在xxx-info.plist里Bundle identifier里替换成你的证书名 xxx是你的工程名 在Bundle iden ... 
- Android:MVC模式(下)
			在上一篇文章中,我们将 View 类单独出来并完成了设计和编写.这次我们将完成 Model 类,并通过 Controller 将两者连接起来,完成这个计算器程序. 模型(Model)就是程序中封装了数 ... 
