本篇文章简单介绍一下关于 MongoDB 索引的一点小知识。好久没没用 MongoDB,经常回顾复习,才能发现自己之前理解的漏洞。
什么是索引
索引就是用来加速查询的。数据库索引与书籍的索引类似:有了索引就不需要翻遍整本书,数据库则可以直接在索引中查找,使得查找速度能提高几个数量级。在索引中找到条目以后,就可以直接跳转到目标文档的位置。
MongoDB 的索引几平与传统的关系型数据库索引一模一样,绝大多数优化 MySQL/Oracle/SQLite 索引的技巧也同样适用于 MongoDB。
创建索引
创建简单索引
MongoDB 创建索引使用 ensureIndex
函数,函数实现可使用 db.system.ensureIndex
查询,实现如下:
1 | function (keys, options) { |
函数接受两个参数 keys
和 options
,其中 keys
表示索引内容,options
表示索引创建附件条件,options
可不传。以下为创建索引的具体示例:
1 | db.UserInfo.ensureIndex({"userAccount": 1}); // 直接根据userAccount创建升序索引 |
题外话: 如何查看 MongoDB 查询的执行过程?请看以下示例。
- 不使用索引的查询
1 | db.UserInfo.find().explain(); // 不使用索引的查询,返回如下: |
- 使用索引的查询
1 | db.UserInfo.find({"userAccount":/abc/}).explain(); // 使用索引的查询,返回如下 |
创建唯一索引
1 | db.UserInfo.ensureIndex({"userNo":1},{"unique":true}); // 创建一个以UserNo为键的唯一索引 |
注意:其中选项 dropDups
在使用时要特别注意,该操作会删除重复文档,建议操作前备份。
后台创建索引
1 | db.UserInfo.ensureIndex({"userAccount":1},{"background":true}); // 后台创建索引 |
注意:非后台建立索引数据库会阻塞建立索引期间的所有请求,建议生产环境或数据量大的环境使用后台创建索引。
自定义索引名
1 | db.UserInfo.ensureIndex({"userAccount":1},{"name":"idx_ua_asc"}); // 直接创建索引并设置索引名称为idx_ua_asc |
注意:索引名最长为127字节,大于127字节的索引名创建索引会失败。
查询索引
MongoDB查询索引使用 getIndexes
函数,函数实现可使用 db.system.getIndexes
查询,实现如下:
1 | function (filter) { |
函数接受一个 filter
参数为查询条件,filter
可不传。以下为查询索引的具体示例:
1 | db.UserInfo.getIndexes(); // 查询所有所有索引 |
删除索引
MongoDB 删除索引使用 dropIndexes
函数和 dropIndex
函数删除索引,函数实现可分别使用 db.system.dropIndexes
和 db.system.dropIndex
查询,函数实现分别如下:
1 | // dropIndexes |
其中 dropIndexes
函数删除除过 _id
键索引以外的全部索引,不接受参数;dropIndex
接受一个 index
参数,删除满足条件的指定索引。具体使用示例如下:
1 | db.UserInfo.dropIndexes(); // 删除所有索引,不包括_id索引 |
更新索引
更新索引使用方法同创建索引,不再赘述。
指定索引查询
1 | db.UserInfo.find({"userAccount":/abc/}).hint({"userAccount":-1}); // 指定索引查询。 |
注意:慎用!MongoDB查询器会智能选择使用最优的索引查询。
地理位置索引
创建索引
1 | db.map.ensureIndex({"gps":"2d"}); // 创建地理位置索引,注意值为"2d" |
注意:"gps"键的值必须是某种形式的一对值:一个包含两个元素的数组或是包含两个键的内嵌文档。下面这些都是有效的:
1 | {"gps": [0,100]}; |
键名可以随意,例如 {"gps":{"foo":100,"bar":100}}
也是可以的。默认情况下,地理空间索引假设值的范围是-180~180,对于经纬度来说非常方便。要是想用其他值,可以通过 ensureIndex
的选项指定最大值最小值。如下:
1 | db.map.ensureIndex({"light-year":"2d"},{"min":-1000,"max":1000}); |
创建复合索引
1 | db.map.ensureIndex({"location":"2d", "desc":1}); // 创建地理空间复合索引 |
查询、删除、修改索引
地理位置索引的查询、删除、修改同上,不再赘述。
关于地理位置查询的题外话
1 | db.map.find({"gps":{"$near":[20,10]}}); // 查找距离点(20,10)最近的点,默认返回100个 |
最后
复习是巩固的最好途径。每一次回头尝试都会有新的理解。
欢迎关注我的公众号 须弥零一,跟我一起学习IT知识。
如果您喜欢此博客或发现它对您有用,则欢迎对此发表评论。 也欢迎您共享此博客,以便更多人可以参与。 如果博客中使用的图像侵犯了您的版权,请与作者联系以将其删除。 谢谢 !