每日分享
The world is moving so fast that the person who says it can't be done is generally interrupted by someone doing it.
世界变化的如此之快,以至于那些光说不做的人,通常被动手去做的人所淘汰。
小闫语录:
少些抱怨,少些碎碎念,将这些时间用在去解决问题上,你会发现问题也许已经解决了。打嘴炮很爽,但是舒服的事情往往都是无意义的消遣。直接动手去干,也许很难,但是你敢于开始就已经成功了一半。不要眼高手低,还是去做,来点实际的比较好。
Mongodb(一)
1.数据库相关知识点回顾
1.数据库分为关系型数据库和非关系型数据库。
2.SQL数据库中包含Oracle(闭源、收费)、MySQL(开源、免费)和SQL Server。
3.三范式:表字段的原子性(不可拆分);满足第一范式的基础上,有主键依赖;满足第一二范式的基础上,非主属性之间没有依赖关系。
比如考试三科成绩的总分,这个字段就是可拆分的,其实是冗余字段。
4.淘宝使用的也是MySQL,但不是直接使用,而是将其改写才使用。因为电商网站的高并发量,涉及到大量读写,没有数据库适用。
5.NoSQL数据库(非关系型数据库):MongoDB、redis。
6.redis是使用c语言编写的、内存型的、支持网络、持久化、key-value形式的非关系型数据库。redis是单线程的。持久化是指自动的将数据保存到磁盘中。
7.mysql是c++写的。
进入一个新的公司尽快熟悉说明文档、数据库表之类的东西。
8.NoSQL有两种解释,一种是Not Only SQL,代表的是不仅仅是数据库;另一种是非关系型数据库。
9.NoSQL指的是非关系型的数据库,是相对于关系型数据库的统称,主要是解决大规模数据存储的挑战。
10.reids存储是键值型的数据,MongoDB则是文档型的数据。
11.SQL注重于关系,NoSQL则是注重存储。NoSQL处理不了特别复杂的关系表。
12.MongoDB是可扩展的高性能、开源、面向文档(分布式文件存储)的NoSQL型的数据库。
13.MongoDB的读写性能在介于redis和mysql之间。redis的性能最高。
redis是内存型,而MongoDB平时存在磁盘,使用时会加载到内存中,MySQL则是磁盘。
14.MySQL的扩展性差,大数据下IO压力大,表结构更改困难。MongoDB易扩展,大数据量高性能,灵活的数据模型,高可用。
15.关系型数据库在当前时代的缺点:数据格式单一;高并发读写性能低;可扩展性低。
2.MongoDB
1.MongoDB中的三要素:数据库、集合(可以简单的理解为表)、文档(可以简单的理解为行)
2.MongoDB中的数据存储是Bson的形式存储的,Bson是二进制的json,所以看上去记录的形式类似于json数据。
3.MongoDB扩展性非常好。因为在MongoDB中文档结构可以不同,随意对文档结构进行扩展,不像MySQL中每个字段都是固定好的,你需要往里填数据。
4.为什么要使用NoSQL?
答:易扩展;读写速度快;高性能和高可扩展;非结构化与不可预知数据(数据模型灵活)。
5.为什么使用MongoDB?
答:高可扩展性;高性能存储;使用简单;部署简单。
2.1MongoDB主要应用场景
1.网站数据:网站实时操作比如插入,更新和查询。
2.缓存:性能高。
3.大量、低价值数据的存储:日志监控数据、爬虫数据。
4.集群
5.json格式的数据:MongoDB采用的Bson(binary json)数据格式。
面试题
一个并发量高的网站,其数据需要实时更新,假如缓存数据和磁盘数据不一致,我们怎么解决这个问题?
答:我们对于访问量高的页面,可以将MySQL数据中的数据读取出来放到redis或者MongoDB中,使得下次访问,直接从缓存中读取即可,提高效率。为了解决缓存数据和磁盘数据不一致,我们可以使用定时任务或者异步,但是都存在一定的缺点。最好的解决方法是:我们在修改相关数据的接口中添加业务逻辑,就是将数据修改后马上删除缓存中的相关数据,使其在访问的时候就直接读取磁盘的内容。
2.2MongoDB安装注意点
1.版本选择时,尽量选取偶数版,偶数版为稳定版(release),基本没有bug。
偶数指版本号为偶数。
2.位数选择64位,32位存在存储上限。
3.安装完只有要记得配置环境变量,使其可以在任意目录下开启使用MongoDB数据库。
4.阻塞进程就是如果关闭当前终端,那么进程就会关闭。守护进程就是可以在后台运行。
5. 27017
是MongoDB的默认端口。redis默认端口是 6379
。MySQL默认端口是 3306
。
2.3基本命令
开启MongoDB服务器:
sudo mongod
数据默认存储在
/data/db
以守护式在后台开启一个子进程:
sudo mongod --logpath=path --dbpath=path --logappend --fork
--dbpath
: 指定数据库的存放路径。
--logpath
: 指定日志的存放路径。
--append
: 或--logappend 设置日志的写入形式为追加模式。不会覆盖。
--fork
: 或 -fork
后台开启新的进程运行mongodb服务。
使用指定的目录存放数据:
sudo mongod --dbpath=/User/data/db
指定加载配置文件:
sudo mongod -f logfile
查看是否开启成功:
ps aux | grep mongod
进入MongoDB的客户端:
mongo
退出客户端:
exit
ctrl + c也可以退出
终端中远程关闭服务器
use admin db.shutdownServer() # 在客户端关闭MongoDB服务器
2.4权限管理
刚安装完毕的MongoDB默认不适用权限认证方式启动,然而公网运行系统要设置权限以保证数据安全。
2.4.1开启权限认证的方式
权限认证默认是关闭的。
1.在启动数据库的时候添加 --auth
参数。以权限认证的方式启动。
sudo mongod --auth
2.在配置文件中添加 auth=true
,然后加载配置文件启动。
2.4.2权限认证创建用户登录的基本步骤
1.首先在普通模式下启动,创建用户,指定权限。
sudo mongod use admin
所有的用户都必须使用管理员账户创建
2.选择数据库后使用相应方法创建用户及权限:
db.createUser( user:"用户名", pwd:"密码", roles:[{role:"权限",db:"数据库"}] )
roles为权限设置的文档,文档中db为指定的数据库,role为权限(常用的权限为root、read、readWrite),其中readWrite为小驼峰的写法。
注意:MongoDB中可以往一个不存在的数据库和集合中进行操作,如果插入数据成功,之后就会自动创建一个数据库。
3.关闭MongoDB服务器,以认证模式启动。
sudo mongod --auth
4.mongo进入终端,切换到admin数据库下,认证:
db.auth('用户名','密码')
返回值为1,表示认证成功。
只能对指定权限的数据库进行相关操作。
2.4.3其他命令
查看已经创建的用户权限:
show users use admin db.system.users.find()
数据库权限认证:(认证的时候必须是该用户在哪个数据库下创建的,在哪个数据库进行认证。)
use dbname
db.auth(user,pwd)
删除某一用户及权限:
db.dropUser(用户名)
在该用户所在的数据库下执行删除命令。
2.5数据库的基本操作
2.5.1数据库相关操作
查看当前使用数据库:
db
查看磁盘上存在的数据库:
show dbs
切换到指定的数据库:
use dbname
1.数据库不存在也可以进行切换。
2.使用use之后并没有创建数据库。
3.数据库是在手动创建集合或者使用集合的时候创建的。
删除当前的数据库:
db.dropDatabase()
使用该命令时必须已经选择了当前要删除的数据库。
2.5.2集合相关操作
查看当前数据库中的集合列表(选择数据库之后使用):
show collections
创建集合:
db.createCollection(name)
删除集合:
db.collection.drop()
2.6固定集合
固定集合类似于循环队列,当没有存储空间的时候,最老的数据将会被新数据覆盖。
MongoDB中集合的存储空间默认最大为16M,也可以使用固定集合指定大小。
创建固定集合:
db.createCollection('集合名称',{capped:true,size:大小})
size的单位是字节。最小有限制为255字节,如果设置的大小小于255,那么会设置为255,但是这一数值根据版本有可能不同。
适用场景:日志。
后面的会将最前面的覆盖掉。
特点:插入速度快,按照顺序查询速度快,新数据会替换旧数据,不能使用remove删除数据。
2.6.1固定集合相关操作
判断一个集合是否为固定大小集合:
db.colname.isCapped()
将一个普通集合转换为固定大小集合,无法将固定集合转换为普通集合:
db.runCommand({"convertToCapped":"colname",size:n})
2.7MongoDB的数据类型
ObjectID
: 文档ID/数据的ID,数据的主键。
4字节时间戳;3字节机器id;2字节进程id;3字节增量值。
此字段如果不指定,系统会自动进行填写,我们也可以进行自定义。
String
: 字符串,最常用,必须是有效的UTF-8
Boolean
: 存储一个布尔值,true或false
Integer
: 整数可以是32位或64位,这取决于服务器
Double
: 浮点数
Arrays
: 数组/列表。
python中的列表,js中的数组。
Object
: mongodb中的一条数据/文档,即文档嵌套文档。
Null
: 存储null值
Timestamp
: 时间戳,表示从1970-1-1到现在的总秒数
Date
: 存储当前日期或时间的UNIX时间格式
3.MongoDB的增删改查
查询操作:
db.colname.find(query)
根据查询条件进行查询,并返回查询结果。
如果不指定query,那么就是所有集合的文档结构。
单条数据插入:
db.colname.insert(data)
data为要插入的数据,格式类似json,或者Python字典,可以直接输入一个字典格式的数据,也可以存一个变量再插入这个变量。
多条数据插入:
db.colname.insert([data_list])
# 多条数据插入
db.t2.insert([{name:'wang'},{name:'zhang'}])
data_list为列表,列表中的每一项都是文档格式(python 字典)
3.1更新操作
语法:
db.colname.update({query},{update})
query为查询条件,update为更新数据
1.全文档覆盖更新
db.colname.update({query},{key,vlaue})
将通过query条件查询出来的文档替换为第二个参数指定的数据
2.指定键值更新
db.colname.update({query},{$set:{key:value}})
将通过query条件查询出来的文档的指定属性设置为指定的值,而不会覆盖原有的其他数据,如果更新值存在则更新,不存在则添加
3.批量键值更新
db.colname.update(query,{$set:{key:value}},{multi:true})
multi决定是否是批量更新还是只更新一条数据,并且只有在对数据字段值操作(使用$)的时候才能使用
multi如果不指定默认为false
4.不指定查询条件进行修改
db.colname.update({},{update},{multi:true})
3.2删除操作
1.指定删除:
db.colname.remove(query,{justOne:boolean})
justOne对应的值决定删除单条数据还是多条数据。
2.删除全部数据:
db.colname.remove({}) # 删除集合的所有数据 db.colname.drop() # 删除集合
3.3保存操作
db.colname.save(data)
save = insert + update
以_id为判断依据,存在该id对应的数据则更新数据,不存在则插入数据
3.4查询操作
多数据查询:
db.colname.find(query)
1.带query则是条件查询
2.不带query是显示集合中的所有数据
单条数据查询:
db.colname.findOne(query)
查询单条数据的时候,返回结果自动美化
查询数据美化:
db.colname.find().pretty()
比较运算符:
符号 | 说明 | 英文 |
$lt | 小于 | less than |
$lte | 小于等于 | less than equal |
$gt | 大于 | great than |
$gte | 大于等于 | great than equal |
$ne | 不等于 | not equal |
比较运算符在查询中格式:
db.colname.find({key:{$lt:n}})
多条件查询, 与
操作:
db.colname.find({key:value,key1:value1}) db.colname.find({$and:[{key:value},{key1:value1}]})
多条件查询, 或
操作:
db.colname.find{$or:[{key:value},{key1:value1}]}
在指定范围中:
db.colname.find({key:{$in:[n1,n2,n3]}})
不再指定范围中:
db.colname.find({key:{$nin:[n1,n2,n3]}})
使用正则表达式:
{key:/正则表达式/} {key:{$regex:’正则表达式’}}
注意:正则表达式只能应用到字符串类型的数据中。
字符串中“123”是将1,2,3分别存储在内存空间的,而整型123是整体指向一块存储空间。
3.5自定义查询
1.为什么有自定义查询?
答:有时候查询条件很复杂,前面的查询方法实现起来都不方便,于是我们可以使用自定义查询搞定复杂操作。
2.什么是自定义查询?
答:自定义查询是使用js语句实现的查询
db.colname.find({ $where:function(){ return this.key > 3 } })
1.以这种方式查询,实际上是对find()的结果应用一遍自定义的js的匿名函数。this的作用同Python的self,this指的是每一条文档。
2.自定义查询可以定义复杂的判断条件。
3.6查询结果的进一步操作
跳过2条数据之后的查询结果:
db.colname.find().skip(2)
限制查询2条数据:
db.colname.find().limit(2)
限制和跳过两个条件混合使用的时候会同步使用,没有先后顺序。
db.colname.find().limit(2).skip(2) 同: db.colname.find().skip(2).limit(2)
投影操作:投影就是显示还是不显示。
db.colname.find({},{_id:0}) # 不显示id db.colname.find({},{_id:1}) # 显示id
id默认是不显示。
排序操作:
db.colname.find().sort({key:1})
sort内不指定条件会报错。
设定数据格式为字典格式,键为排序依据的字段,值决定升序还是降序。1表示升序,-1表示降序
统计操作:
1. db.colname.find(query).count() 2. db.colname.count(query) 消除重复操作:
db.colname.distinct('字段名',{条件})
字段名中使用字符串。
4.MongoDB的索引
4.1面试题
索引的原理?
答: 二叉树/B+树/红黑树
。
4.2 索引
索引可以提升查询速度,提升数据库查询的性能,但是牺牲了数据库的插入和更新速度。频繁插入修改的数据不适合建立索引。
最大的缺点就是在插入数据的时候,之前的索引就会变化。
查看语句的执行情况:
db.colname.find(query).explain(‘executionStats’)
创建索引的方法:
db.集合名.ensureIndex({属性:1})
创建索引使用的文档中键为设置索引的字段,值为1表示索引按照升序存储,值为-1则表示索引按照降序存储。
当有大量数据时,创建索引会非常缓慢,因此可以后台创建索引,在创建索引的时候添加{background:true}
db.colname.ensureIndex({key:1},{background:true})
联合索引:
db.colname.ensureIndex({key1:1,key2:1} # 创建联合索引之后,可以使用key1或者key1,key2的查询进行查找
查看已经存在的索引:
db.colname.getIndexes()
创建唯一索引:
db.colname.ensureIndex({‘key’:1},{“unique”:true})
注意:当创建一个key为唯一索引时,新插入的数据如果key的值与已存在的数据相同,则会报错。当对已存在数据的集合创建唯一索引时,可能会因为重复,导致创建不成功,使用dropDups可以删除重复文档,但是我们一般不建议使用:
db.colname.ensureIndex({‘key’:1},{“unique”:true,”dropDups”:true})
删除索引:
db.colname.dropIndex({‘key’:1})
5.备份和恢复
1.为什么进行数据备份?
答:数据备份指的是将数据备份到指定的目录,并在需要的时候进行恢复,一般用于灾难处理。
2.进行备份(在终端中使用命令):
mongodump -h host -d dbname -o directionary
3.如何进行数据恢复:
mongorestore -h host -d dbname --dir directionary
5.1数据的导出和导入
导出成json文件:
mongoexport -d dbname -c colname -o stu.json
导出成csv文件:
mongoexport -d dbname -c colname --type csv -f filed1,filed2,… -o filename.csv
为什么进行数据的导出遇导入?
答:数据库中的数据在与其他平台和应用进行交互时需要按照指定格式导出交给后续步骤进行处理。
6.python与MongoDB的交互
导入
from pymongo importMongoClient
创建连接的数据库对象
client=MongoClient(host,port)
连接池默认是100个。
指定连接的数据库/集合/文档
stu = client['Ethanyan']['stu']
p
ython中find查询返回的是cursor对象,需要对游标对象进行遍历,得到查询结果 1. # 遍历游标对象 2. for i in stu.find(): 3. print(i)
7.面试题
关系型和非关系型数据库?
答:关系型指二维表格的形式存储数据,列叫做字段、行叫做记录,表和表之间有关系,主键、外键、引用。非关系型数据库是文档形式存储数据,没有表的概念,有集合(表)和文档(记录),存储基于硬盘存储数据,吧硬盘中的数据放入内存中进行读写操作。