mongoDB
什么是NOSQL
NoSQL,其中No指代“non-relational”,仅仅是一个概念,泛指非关系型的数据库
对比RDS
相比于RDS(关系型数据库服务,relational database service),非关系数据库有如下差异
-
不保证关系数据的ACID特性(原子、一致、隔离、持久)
-
NoSQL具有非常高的读写能力,尤其在大数据量下,得益于其无关系性以及数据库的结构简单
-
不同于关系型,存在有键值对、列、文档等数据存储类型
-
随时可以存储自定义的数据格式,数据模型灵活
-
支持的数据结构松散,类似json的bson(二进制JSON)格式,可以存储比较复杂的数据类型
市面产品
目前市场上应用较多的是Redis和mongoDB,下面主要对比一下二者之间的区别
1.内存管理机制
Redis 数据全部存在内存,定期写入磁盘,当内存不够时,可以选择指定的 LRU 算法删除数据。
MongoDB 数据存在内存,由 linux系统 mmap 实现,当内存不够时,只将热点数据放入内存,其他数据存在磁盘。
redis比mongo更依赖内存
2.支持的数据结构
Redis 支持的数据结构丰富,包括hash、set、list等。
MongoDB 数据结构比较单一(如json格式),但是支持丰富的数据表达,索引,最类似关系型数据库,支持的查询语言非常丰富。
3.数据量和性能
当物理内存够用的时候,redis>mongodb>mysql
当物理内存不够用的时候,redis和mongodb都会使用虚拟内存。
实际上如果redis要开始虚拟内存,那很明显要么加内存条,要么你换个数据库了,但是mongodb不一样,只要业务上能保证冷热数据的读写比,使得热数据在物理内存中,mmap的交换较少,mongodb还是能够保证性能。
4.性能
mongodb依赖内存,TPS较高;Redis依赖内存,TPS非常高;性能上Redis优于MongoDB。
5.可靠性
mongodb从1.8版本后,采用binlog方式(MySQL同样采用该方式)支持持久化,增加可靠性;
Redis依赖快照进行持久化;AOF增强可靠性;增强可靠性的同时,影响访问性能。
可靠性上MongoDB优于Redis。
6、数据分析
mongodb内置数据分析功能(mapreduce),而Redis不支持。
7.事务支持情况
Redis 事务支持比较弱,只能保证事务中的每个操作连续执行
mongodb目前只支持单文档事务
8.集群
MongoDB 集群技术比较成熟,Redis从3.0开始支持集群
MongoDB简介
MongoDB是一个基于分布式文件存储的数据库,由C++编写,本质上是给数据日益增加的WEB应用提供一个高性能数据存储解决方案。MongoDB是介于RD和NoSQL之间的产品,是NoSQL当中功能最丰富,最像RDS的
mongoDB官方文档地址:https://docs.mongodb.com/manua
支持的数据类型
数据类型 | 描述 |
---|---|
String | 字符串。存储数据常用的数据类型。在 MongoDB 中,UTF-8 编码的字符串才是合法的。 |
Integer | 整型数值。用于存储数值。根据你所采用的服务器,可分为 32 位或 64 位。 |
Boolean | 布尔值。用于存储布尔值(真/假)。 |
Double | 双精度浮点值。用于存储浮点值。 |
Min/Max keys | 将一个值与 BSON(二进制的 JSON)元素的最低值和最高值相对比。 |
Array | 用于将数组或列表或多个值存储为一个键。 |
Timestamp | 时间戳。记录文档修改或添加的具体时间。 |
Object | 用于内嵌文档。 |
Null | 用于创建空值。 |
Symbol | 符号。该数据类型基本上等同于字符串类型,但不同的是,它一般用于采用特殊符号类型的语言。 |
Date | 日期时间。用 UNIX 时间格式来存储当前日期或时间。你可以指定自己的日期时间:创建 Date 对象,传入年月日信息。 |
Object ID | 对象 ID。用于创建文档的 ID。 (每个文档都有) |
Binary Data | 二进制数据。用于存储二进制数据。 |
Code | 代码类型。用于在文档中存储 JavaScript 代码。 |
Regular expression |
安装
为避免各位同学找不到下载地址,特将下载地址贴出,记得选择社区版
mongoDB官方安装地址:https://www.mongodb.com/try/download/community
PS:如果安装企业版需要注册帐号,社区版方便快捷
window版安装
下载window版的安装包,选择最新版,格式为zip包
步骤1:解压
在自己选择的磁盘中创建文件夹mongodb,将下载好的压缩包中的内容移动自其中,此处以E盘为例,其中需要注意的是解压后的文件必须是bin这一级
步骤2:创建日志和数据文件夹
再在对应的data文件夹中创建db文件夹
步骤3:管理员执行控制台命令
管理员身份打开dos命令,之后键入如下指令
#跳转到指令的目录下
cd E:\mongodb\bin
#设置数据文件路径 创建mongodb.log日志文件
mongod --install --dbpath E:\mongodb\data --logpath E:\mongodb\logs\mongodb.log --logappend
执行成功后对应的MongoDB服务会被创建
步骤4:创建MongoDB为windows服务
因为window下没有fork参数,因此此设置是为了让MongoDB在windows下静默运行,即后台运行
sc create MongoDB binPath= "E:\MongoDB\bin\mongod.exe --service --dbpath E:\mongodb\data --logpath=E:\mongodb\log\mongodb.log --logappend"
PS:如果提示已经创建,则忽略此步骤
步骤5:启动MongoBD服务
net start mongodb
如果想关闭服务,可以使用
net stop mongodb
步骤6:登录MongoDB
mongo
如果登录成功,会提示如下界面
#步骤7 配置bin路径到环境变量path路径
此步骤省略,与以前JDK配置类似,只需要将MongoDB的安装路径下的bin路径复制到指定的环境变量path中即可
linux版安装
linux后期讲到服务器部署时专门进行讲解,后期讲解的linux为常用的centOS,此处先放出mongoDB的linux版安装所需要的一些指令
步骤1:通过wget指令远程下载mongodb,通过copylink的方式复制下载地址
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel80-4.4.1.tgz
步骤2:解压对应的压缩包
tar -zxvf mmongodb-linux-x86_64-rhel80-4.4.1.tgz
步骤3:拷贝解压后的文件到指定路径
mv mongodb-src-r4.4.1 /usr/local/mongodb
步骤4:配置mongoDB变量(与以前JDK配置一样)
#案例
export PATH=mongodb安装地址/bin:$PATH
export PATH=/usr/local/mongodb/bin:$PATH
步骤5:创建数据库目录
MongoDB 启动后会初始化以下两个目录
- 数据存储目录:/var/lib/mongodb
- 日志文件目录:/var/log/mongodb
我们在启动前可以先创建这两个目录并设置当前用户有读写权限:
sudo mkdir -p /user/local/mongodb/data /user/local/mongodb/logs #创建数据和日志文件
sudo chown `jish` /var/lib/mongodb # 设置权限
sudo chown `jish` /var/log/mongodb # 设置权限
步骤6:启动 Mongodb 服务
/user/local/mongodb/bin/mongod --dbpath=/user/local/mongodb/data --logpath=/user/local/mongodb/logs/mongod.log --logappend --port=27017 --fork
步骤7:打开mongoDB
/user/local/mongodb/bin/mongodb
如果打开后发现有启动成功(sucessfully)字样,则证明启动成功
权限配置
与之前的mysql一样,可以创建某个用户并为其设置对应的数据库权限,具体的设置语法如下
创建角色语法
use 数据库名
db.createUser({
"user":"登录帐号",
"pwd":"登录密码",
"roles":[{
role:"内置角色",
db:"所属数据库"
}]
})
角色权限
内置角色:
1. 数据库用户角色:read、readWrite;
2. 数据库管理角色:dbAdmin、dbOwner、userAdmin;
3. 集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager;
4. 备份恢复角色:backup、restore;
5. 所有数据库角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase
6. 超级用户角色:root
7. 内部角色:__system
// 这里还有几个角色间接或直接提供了系统超级用户的访问(dbOwner 、userAdmin、userAdminAnyDatabase)
部分角色解释说明:
read:允许用户读取指定数据库
readWrite:允许用户读写指定数据库
dbAdmin:允许用户在指定数据库中执行管理函数,如索引创建、删除,查看统计或访问system.profile
userAdmin:允许用户向system.users集合写入,可以找指定数据库里创建、删除和管理用户
clusterAdmin:只在admin数据库中可用,赋予用户所有分片和复制集相关函数的管理权限。
readAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读权限
readWriteAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读写权限
userAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的userAdmin权限
dbAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的dbAdmin权限。
root:只在admin数据库中可用。超级账号,超级权限。
操作步骤
1.创建角色
use admin
db.createUser({
"user":"sa",
"pwd":"sa",
"roles":[{
role:"root",
db:"admin"
}]
})
#验证用户是否插入成功
db.system.users.find().pretty()
2.卸载mongoDB服务
#管理员身份运行
mongod --remove
3.重新安装mongoDB服务
mongod --install --dbpath E:\mongodb\data --logpath E:\mongodb\logs\mongodb.log --logappend --auth
4.服务重启,登录
net start mongodb
#mongo直接登录
mongo
#show dbs 发现发现并没有发现数据库
show dbs
登录方式
方式一
mongo [IP:端口号/数据库名] -u用户名 -p密码
案例
# mongo 127.0.0.1:27017/admin -usa -psa
#不写默认进入的是admin库
mongo -usa -psa
方式二
use admin
db.auth("sa","sa")
多用户权限管理案例
此处演示一个案例,创建2个库,并分别对2个库创建对应的用户,进行相应的权限设置
添加数据
use myTest
for(var i = 1; i <= 3; i++){
db.fang.insert({"name":"fang"+i,"age":i})
}
创建2个用户
db.createUser({
"user":"zz",
"pwd":"zz",
roles:[{
"role":"read",
"db":"myTest"
}]
})
db.createUser({
"user":"jj",
"pwd":"jj",
roles:[{
"role":"readWrite",
"db":"myTest"
}]
})
验证是否有效
use admin
db.system.users.find().pretty()
登录zz帐号,往myTest中添加数据,发现被拒绝
mongo 127.0.0.1:27017/myTest -uzz -pzz
#下列写法均可
# mongo 127.0.0.1:27017/myTest -u zz -p zz
# mongo localhost:27017/myTest -u zz -p zz
删除用户
db.dropUser("用户名") 根据用户名删除指定用户
db.dropAllUser() 删除所有用户
注意,需要使用拥有权限的用户进行删除处理,如一开始添加的root权限用户,如果实在删不掉,就用删除所有用户的方式
常用语法
数据库
展示数据库
这个与之前学习的其他数据库一样,系统会默认提供3个库
show databases
选择数据库
也是与之前相同的语法,只不过有一点不同的是,选择不存在的数据库,也不会报错,如果用户在选择的这个不存在的库A中去创建数据,则系统会隐式创建库A(通常也是用隐式创建的方式)
use stusys
删除数据库
删除指定数据库与以前有点不同
use 指定数据库
db.dropDatabase() 删除指定数据库
集合
集合是Mongodb中数据的存储模式,类似集合中
查看集合
show collections
创建集合
db.createCollection('集合名')
案例
db.createCollection('myCollection')
注意
实际上,在MongoDB中也无需显示创建集合,与选择数据库时隐式创建相同,往一个指定集合中添加数据,也可以隐式创建该集合
删除集合
需要注意的是,需要指定集合名称
db.集合名.drop()
CRUD
新增
db.集合名.insert(集合内容,格式与json类似)
案例
注意,此案例隐式创建了数据库test以及集合my1
use test
db.fang2.insert({name:"fanglaoc",age:"18"})
for(var i = 0; i < 100 ; i++){
db.fang.insert({name:"fang"+i,age:i});
}
补充
1.默认UUID
插入时默认添加的_id(UUID)也可以在插入数据的同时一并添加,但通常不需要手动覆盖,默认提供的UUID即可
db.fang2.insert({_id:"1",name:"fanglaoc",age:"18"})
2.多行插入
通过上面的插入案例可以得知,实际上插入的数据为json格式数据,对于多条数据只需要定义json格式的数组即可
db.fang2.insert([
{name:"fang",age:"13"},
{name:"zhi",age:"14"},
{name:"jian",age:"15"}
])
3.JS支持
mongoDB本身也支持部分js语法,比如也可以通过for循环进行遍历插入
for(var i = 1; i <= 10; i++){
db.fang2.insert({name:"fang"+i,age:i});
}
查找
基础案例
通过该指令可以查找集合名下的所有内容
db.集合名.find()
注意:在插入一条数据后,mongodb会默认为我们新增一个UUID作唯一表示,关于UUID的组成,实际上是由 :时间戳(4位)+ 机器码(3位)+ PID(2位)+ 计数器(3位)
查找进阶
语法
db.集合名.find(条件[,查询列])
条件语法
注意:此处单引号 双引号均可,只需要记住和json格式相似即可
查询所有数据 {}或者不写
查询指定条件如姓名 {name:"fang"}
多条件查询 {name:"fang",age:"18"}
模糊查询(实际上就通过正则表达式来实现)
方式1:{name:{$regex:"fang"}}
方式2:{name:/fang/}
范围区间查询: 需要结合运算符,以前学过的<>但需要注意此处使用的是$lt $gt
in查询 {age:{$in:[3,5,18]}}
db.fang.find({age:{$in:[1,10,99]}})
条件案例
1、单条件查询
2、复合条件查询
3、模糊查询
4、范围区间查询
范围区间查询需要使用到运算符,以下为常用的运算符
- $gt 大于
- $gte 大于等于
- $lt 小于
- $lte 小于等于
- $ne 不等于
- $in in区间
- $nin 不在in区间
案例
查询年龄大于8岁的用户
db.fang2.find({age:{$gte:8}})
查询年龄在3到10岁之间的用户
db.fang2.find({
age:{$gte:3,$lte:10}
})
5、in查询
db.fang2.find({age:{$in:[1,3,18]}})
如果查询的为"“,则表示查询的为字符串,如果不带”",则表示查询的为数字类型
查询列
需要注意的是,0和1分别表示的是排除指定列和包含指定列
db.集合名.find({条件},{age:0})
db.集合名.find({条件},{age:1})
查找结果美化
对于查找后的json格式数据,如果希望格式化,可以使用pretty()
db.fang2.find().pretty()
修改
语法
--较少使用,本质为替换
db.集合名.update(条件,新数据)
--较多使用
db.集合名.update(条件,{修改器:{键:值}})
db.集合名.update(条件,新数据[,是否新增(默认false),是否修改多条(默认false)])
案例
db.集合名.update(条件,新数据)
将年龄为3的用户名改为jojo
db.fang2.update({age:3},{name:"jojo"})
db.集合名.update(条件,{修改器:{键:值}})
常见修改器
- $inc 递增 减少用负数 如 $inc:
- $rename 重命名列
- $set 修改列值
- $unset 删除列
db.fang2.update({age:4},{$set:{name:"jojo"}})
多个修改器复合使用
db.集合名.update(条件,{
修改器:{键:值},
修改器:{键:值},
修改器:{键:值}
})
将name为jojo的行的name属性改为nickname,年龄增加12岁
db.fang2.update({name:"jojo"},{
$inc:{age:12},
$rename:{name:"nickname"}
})
db.集合名.update(条件,新数据[,是否新增(默认false),是否修改多条(默认false)])
是否新增
如果没有符合条件的数据行,则默认为你创建一条数据
db.fang2.update({age:11},{$set:{age:11,name:"fang11"}},true)
本身虽然没有age11的数据,但为我们自动创建了
小实验:如果更新一条不存在的数据,并且采用$inc的方式,可以发现一样会为我们创建一条新的,并且是基于原有数据12去加1
db.fang2.update({age:12},{$inc:{age:1}},true)
如果不以age为条件,此时$inc设置的age,会变为新建数据行的初始值
db.fang2.update({name:"fang12"},{$inc:{age:1}},true)
是否修改多条
这实际上是mongoDB的保护机制,避免用户批量修改过多数据导致数据出错,因此每次更新都是默认更新满足条件的1条,如果将其设置为true,则可以修改所有
将名字包含fang的所有数据的年龄都设置为100
db.fang2.update({name:/fang/},{$set:{age:100}},false,true)
可以发现所有包含fang的行年龄都变为100
删除
语法
默认为false,即删除符合所有条件的数据行
db.fang2.remove(条件[,是否删除一条])
案例
--删除名字自中带有fang的,删除一条(较少使用)
db.fang2.remove({name:/fang/},true)
--删除名字自中带有fang的,删除全部
db.fang2.remove({name:/fang/})
其他函数
skip和limit
当我们使用分页查询时,在mysql中使用的是如下语法
select * from student limit [index,]columns
index表示起始索引,columns表示每次查询的总行数
select * from student limit 5,5
查询所有学生信息,从第6条数据开始,每次查询出5条
但是在mongoDB中,limit只有一个参数,因此想要实现分页功能,需要借助skip和limit一起实现
案例集合:
for(var i = 1; i <= 20; i++){
db.fang3.insert({name:"fanglaoc",age:i})
}
单独使用limit()函数,则表示从第1条数据开始,查找符合条件的前5条
db.fang2.find().limit(5)
等价于db.fang2.find().skip(0).limit(5)
如果希望每页5条,查找第4页(最后1页),可以分析得知,第16条开始,下标为15
#此公式和当时讲解的mysql分页的公式一样
起始下标 = (当前页数 - 1) * 每页分页
db.fang3.find().skip(15).limit(5)
sort
在以前mysql,我们对于查询到的数据进行升序排序时,使用的是order by关键字,而在mongoDB中,我们使用的是sort函数
db.fang3.find().sort({age:1}).skip(15).limit(5)
sort中,sort({age:1})表示按年龄升序排序,sort({age:-1})表示按年龄降序排序
但此处可以发现一个问题,如果多个函数,sort,limit,skip一起使用时,在降序时会发现结果并不是20 19… 16,这是因为mongoDB中 skip、limit、sort有优先级
顺序为:sort>skip>limit
问题解决
利用下面要讲解的 aggregate(聚合函数),利用其管道流的性质,可以解决优先级问题
db.getCollection(‘fang3’)是获取fang3这个集合,然后利用aggregate聚合函数的特性,设置函数的优先级
注意:db.getCollection(‘fang3’)和db.fang3等价
#db.getCollection('fang3').aggregate([{$skip:15},{$limit:5},{$sort:{age:-1}}]);
db.fang3.aggregate([{$skip:15},{$limit:5},{$sort:{age:-1}}]);
db.jojo.aggregate([
{$skip:5},
{$limit:5},
{$sort:{age:-1}}
])
聚合函数(aggregate [ˈæɡrɪɡət , ˈæɡrɪɡeɪt])
MongoDB中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等)
对于一些函数的默认优先级不方便使用的情况,可以利用aggregate的管道流的性质,将MongoDB文档在一个管道处理完毕后将结果传递给下一个管道处理,进而各类函数优先级问题
语法
db.集合名称.aggregate([
{管道:{表达式}}
...
])
管道
$group 将集合中的文档分组,可用于统计结果
$match 用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作
$sort 将输入文档排序后输出
$skip 在聚合管道中跳过指定数量的文档,并返回余下的文档
$limit 用来限制MongoDB聚合管道返回的文档数
#较少使用
$project:修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档
$unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值
$geoNear:输出接近某一地理位置的有序文档
常用表达式
$sum 计算总和 #其中$sum:1与count等价,表示数量统计
$avg 计算平均值
$min 获取集合中所有文档对应值得最小值
$max 获取集合中所有文档对应值得最大值
#较少使用
$push 在结果文档中插入值到一个数组中
$addToSet 在结果文档中插入值到一个数组中,但不创建副本
$first 根据资源文档的排序获取第一个文档数据
$last 根据资源文档的排序获取最后一个文档数据
案例
示例数据
use test
db.fang4.insert({name:"丽丽",age:15,gender:"女"})
db.fang4.insert({name:"花花",age:15,gender:"女"})
db.fang4.insert({name:"咪咪",age:10,gender:"男"})
db.fang4.insert({name:"帅帅",age:10,gender:"男"})
db.fang4.insert({name:"兵兵",age:20,gender:"男"})
案例一
统计fang4集合中的男女的人数
gender,如果不希望分组则将 _id的值设置为null
count为自己定义的名称,{$sum:1}则等价于计数函数count
db.fang4.aggregate([
{
$group:{
_id:"$gender",
count:{$sum:1}
}
}
])
案例二
统计fang4集合中的男女的年龄总和
db.fang4.aggregate([
{
$group:{
_id:"$gender",
count:{$sum:"$age"}
}
}
])
案例三
统计fang4集合中年龄最大的女性
group管道用于数据分组,从逻辑上来讲,是先筛选出指定类型的数据,再进行分组,因此match管道放在group管道前面
db.fang4.aggregate([
{
$match:{
gender:"女"
}
},
{
$group:{
_id:null,
min:{$max:"$age"}
}
}
])
db.fang4.aggregate([
{
$match:{
age:{$gte:0,$lt:20}
}
},
{
$group:{
_id:"$gender",
total:{$sum:1},
avg:{$avg:"$age"}
}
}
])
案例四
统计fang4集合中学小于20岁的男女学生总数和平均年龄
db.fang4.aggregate([
{
$match:{
age:{$gte:0,$lt:20}
}
},{
$group:{
_id:"$gender",
count:{$sum:1},
avg:{$avg:"$age"}
}
}
])
案例五
按照指定要求进行分组查询,以fang3集合为例(20条数据的那个),每页数量为5条数据,从第2页开始,查询满足年龄在10岁以上(含10岁)的学生信息,并按照年龄降序排序
db.fang3.aggregate([
{$match:{age:{$gt:10}}},
{$skip:5},
{$limit:5},
{$sort:{age:-1}}
]);
索引
此处的索引与mysql相同,用于加快的检索速度,本质上的数据结构为 排序二叉树
优点
毋庸置疑,减少CPU损耗和数据库成本,大大加快检索速度,(尤其对于经常检索的条件列,因此一般索引就加在这样的列上)
缺点
- 索引本身占据一定的空间
- 过多索引一定程度会影响SQL语句(主要是新增、修改、删除)执行效率,因为这些操作需要更新索引
创建索引
语法
db.集合名.createIndex(待创建索引的列[,额外选项])
参数解释
待创建的列:{键:1...,键:-1}
1表示升序 -1表示降序 {id:1}创建id索引并索引按照升序方式存储
额外选项可以设置索引名以及唯一索引
查看所有索引
语法
db.集合名.getIndexes()
删除索引
语法
删除指定索引
db.集合名.dropIndex(集合名)
全部索引删除
db.集合名.dropIndexes()
案例
0、基础数据准备
use indexTest
for(var i = 1; i <= 20000; i++){
db.fang.insert({name:"fang"+i,age:i});
}
1、普通索引
如果用户经常对用户名使用模糊查询,在这样的场景下可以为name设置索引
db.fang.createIndex({name:1})
2、索引删除
如果对于上面的索引不想要了,可以删除对应的索引
db.fang.dropIndex("name_1")
3、创建自定义名索引
db.fang.createIndex({"name":1},{"name":"fang_name_index"})
4、复合索引
与以前学习的复合主键类似,复合索引即表示为多个列创建索引,如果有些查询带有多个条件时可以使用
db.fang.createIndex({name:1,age:-1},{name:"name_age_index"})
5、唯一索引
与以前讲解的主键约束一样,为某一列定义主键实际上就是为主键列设置一个索引,并且添加一个唯一约束,唯一索引的主要作用是避免列插入重复的值
db.fang.createIndex({name:-1},{name:"name_index","unique":"name"})
如果插入重复的或者之前的数据列存在重复数据想添加唯一索引,都会引发错误冲突
索引效率校验
对比下性能差距,此处可以通过explain函数实现对某个sql的性能检测
其中executionStats中executionStages的属性值有几个值,如:
- COLLSCAN 全表扫描
- IXSCAN 索引扫描
- FETCH 根据索引检索指定document
语法
db.集合名.find(条件).explain("executionStats")
案例
添加索引情况
db.fang.find({age:1}).explain("executionStats")
不添加索引情况
同样的执行语句,把对应的索引进行删除
db.fang.find({age:1}).explain("executionStats")
可视化工具
mongoDB常用的可视化工具有很多,此处使用的是NoSQLBooster for MongoDB
下载地址:https://www.mongobooster.com/downloads
技术选型
对于mongoDB的使用场景其实有很多,当然在性能上考虑很多公司还是会考虑用redis,但在某些场合下,mongoDB的性能会比redis快,以下场景可以考虑使用mongoDB
1、公司业务不要求事务且sql语句简单,无需过多繁琐join语句
2、数据模型不确定但又想要快速迭代
3、数据高读写速度
4、项目需要大量的地理位置查询、文本查询
5、项目本身需要较大数据存储(硬盘是mongo的一大优势)