整理mongodb文档:索引

个人博客

整理mongodb文档:索引

个人博客,求关注,有问题的地方欢迎指出,觉得讲解的繁琐的也请指出

文章概叙

本文主要还是在shell下的操作。让大家了解下mongodb中index的用途,基本的索引的新增、查看、删除等,最后再提一嘴复合索引。

数据准备

大家都知道mongodb跟javaScript的关系,所以我就不解释为什么用下面的sql来创建百万条数据了,我可不想自己手动输入百万条数据。

javascript 复制代码
db.test.insertMany(
    new Array(1000000).fill(1).map((v, index) => {
        return {
            index,
            single_digit: index % 10,
        }
    })
);

比如我们想要查询出所有的个位数为2的数据,我们用find方法查询,但是为了看下查询的状态,我们使用下面的sql,增加了explain方法

javascript 复制代码
db.test.find({single_digit:2}).explain("executionStats")

explain 操作提供了查询信息,使用索引及查询统计等。有利于我们对索引的优化

executionStats顾名思义,代表的是运行时候的状态,关于explain的后续会有一个博客讲解下,这儿主要是让大家知道正常情况下运行find方法的"消耗",方便对后面做对比。

executionTimeMillis 代表的是运行的时间,显示的时间是1198ms。

totalDocsExamined 代表的是我们去检查的文档的总数,正好一百万,说明人家遍历了我们整个集合。

总结一句,find方法遍历了我们的文档,并且花费了1.198s的时间去返回我们想要的数据。

接着我们进入索引的范畴。

获取索引列表

javascript 复制代码
db.test.getIndexes()

可以看到,默认有一个索引,叫做"_id",也就是唯一id,这个可以理解,毕竟人家是唯一id,而且官网上的解释也很清晰。

在创建集合期间,MongoDB 在_id字段上创建唯一索引。该索引可防止客户端插入两个具有相同值的文档。你不能将_id字段上的index删除。

其中,v表示的是当前索引系统的版本,其余的两个参数,分别代表索引的名字还有索引的内容,看完下面的介绍,肯定就会明白的。

创建索引

现在我们已经知道有一个默认的_id索引了,接下来需要创建一个关于single_digit的索引,方便我们后续的查询。

javascript 复制代码
db.test.createIndex()

结合到我们的例子中,便是

javascript 复制代码
db
    .test
    .createIndex({ single_digit: 1 })

其中,single_digit代表的是我们的索引字段。

1代表该索引使用升序方式排序,-1则表示使用降序。最主要是理解到单个索引是如何使用的。

对于单字段索引和排序操作,索引键的排序顺序(升序或降序)并不重要,因为MongoDB可以从任何方向遍历索引。

可以看到,现在创建了一个名字叫做single_digit_1的,而由于该索引只有一个字段,所以我们称呼为单字段索引。

再有了索引的条件下,我们重新用find方法查询下db

可以看到,在用了索引的条件下,使用了346ms的时间,查询了十万条数据,返回了十万条数据。

至此,我们可以理解为索引就是根据特定的条件,对数据进行分类,用户根据条件查询的时候,如果击中了索引的条件,就直接使用索引去查询,这样子能节省时间。

需要注意的是,如果索引已经存在了,再创建一个相同的索引的时候,是无效的,不做例子介绍了,可以自己再创建一个"single_digit"为-1的测试下。

删除索引

有了新增,也就有了删除,尤其是索引这种很占用内存的东西上

javascript 复制代码
db
    .test
    .dropIndex('single_digit_1')

如果是删除所有的索引,可以使用

javascript 复制代码
db
    .test
    .dropIndexs()

删除索引的方法没什么需要注意的,对我们来说,有参数就是删除特定索引,没有参数就是直接删除所有的索引

重建索引

首先,让我们将刚刚的single_digit索引加回来。此时,先贴一段话

db.collection.reIndex() may only be run on standalone instances. For

most users, the db.collection.reIndex() command is unnecessary.

大概翻译过来就是,对于大部分的用户来说,reIndex是不必要的。而且reIndex在6.0之后会被废弃,所以我依旧建议看看就行。

假设下面的情况,我们的数据库中现在有100万条数据,而现在的索引,是基于当前的数据建造的,那么如果我们再加入100万条数据,我们是否要重新去创建一次索引呢?首先答案是否定的,具体可以从stats方法去查看出当前数据的状态

javascript 复制代码
db.test.stats()

其中可以看到当前的索引大小为10MB,而更新之前的大小为5MB.建议大家自己看看stats指令的作用。

实际开发中,reIndex的作用很小,如果有参数的时候,更新的是特定的索引,用法如下

javascript 复制代码
db
    .test
    .reIndex({ "single_digit_1": 1 })

而当不赋予参数之后,则表示更新全部的索引

javascript 复制代码
db
    .test
    .reIndex()

请注意,更新索引的代价是很高的。需要重新遍历一次数据去重建索引,所以很不建议,尤其是新手,要更新索引,必须先问下你的boss,然后再确定找个空闲的时间更新

知道了最简单的索引的创建、删除,以及对索引的"更新",对于索引就有了大概的了解了。接下来重点放在索引的类型上。

复合索引

很多情况下,我们的查询并不是只有一个关键字段,假设一个系统中,我们要遍历出所有的广东省的男性,这时候我们的sql就需要两个条件,分别是男性以及广东省,此时就可以创建一个复合索引,如下(数据随便创建了几条)

javascript 复制代码
db
    .orders
    .createIndex({ province: 1, gender: 1 })

复合索引中列出的字段的顺序很重要。索引将包含对文档的引用,这些文档首先按item字段的值排序,然后在该字段的每个值内item,按stock字段的值排序。有关更多信息,请参见排序顺序。

大概意思就是,当我们创建复合索引的时候,我们需要注意列出的字段的顺序。比如这儿列出的是省份,才是性别。

新手可以粗略的理解为后面使用index查询的时候,先击中省份,再击中性别,如果想要知道具体的,建议查询官网中关于mongodb的ESR。

复合索引能很大程度的降低查询的时间,但是有最多32个字段的限制,而且索引并不是越多越好的。过多的索引会造成很多的内存占用。

对于其他的索引类型。比如文本索引以及通配符索引,可以大概去官网查看下,如果写了,篇幅会过大,且新手没掌握的时候会云里雾里,所以我就不展开了。

最后的话

简单来说,索引的作用就是为了更快得查询数据,很多时候单字段的索引足够满足我们的需求,对于部分较为常用的数据,可以使用复合数据。

但是索引需要用到内存,本质上是将部分的数据做了处理后将其保存下来,方便我们的查询,但是盲目创建索引,会让自己的项目越来越卡顿。

如果想知道自己的sql是否使用了index,可以使用explain()指令,查看是否用的"IXSCAN"(索引查询),以及使用的是哪一个index。

不建议指定index的名字,所以博客中并没有指出如何设置name。

相关推荐
行走的山峰8 分钟前
etcd三节点,其中一个坏掉了的恢复办法
数据库·etcd
ImomoTo3 小时前
HarmonyOS学习(十三)——数据管理(二) 关系型数据库
数据库·学习·harmonyos·arkts·鸿蒙
机器视觉知识推荐、就业指导6 小时前
Qt/C++事件过滤器与控件响应重写的使用、场景的不同
开发语言·数据库·c++·qt
jnrjian6 小时前
export rman 备份会占用buff/cache 导致内存压力
数据库·oracle
isNotNullX7 小时前
一文解读OLAP的工具和应用软件
大数据·数据库·etl
小诸葛的博客8 小时前
pg入门1——使用容器启动一个pg
数据库
大熊程序猿9 小时前
python 读取excel数据存储到mysql
数据库·python·mysql
落落落sss9 小时前
sharding-jdbc分库分表
android·java·开发语言·数据库·servlet·oracle
jnrjian9 小时前
Oracle 启动动态采样 自适应执行计划
数据库·oracle