计算机速度比较: CPU -> 寄存器 -> 缓存L1/L2/L3 -> 内存 -> 硬盘 -> 网卡 -> BIOS
LMAP: Linux + MySQL + Apache + PHP/Python
Windows Server + SQL Server + ASP.net
SQL(MySQL、Oracle、DB2) 应用场景 :
1. 高度要求事务性场景、银行、物流、贸易、金融,需要大量原子性操作(多个操作共存亡)。
2. 需要持久化存储的 "冷数据" (无需经常改动的数据)。
3. 对安全性要求高的数据(SQL已沉淀几十年, 成熟稳定)。
4. 需要通过统一的 SQL语句 处理的场景(非关系型数据库的语法各不相同)。
5. 业务需要明确的多表结构关系的设计和字段的设计(表间关系错综复杂, 需要经验丰富的架构师)。
NoSQL(内存+硬盘) 应用场景 :
1. 拥有灵活的数据结构, 但也需事先设计表结构关系。
2. 需要存储 IO要求高、"热数据" (随时改动的数据) 的场景[NoSQL基于内存,速度高效]。
3. 高度伸缩性,更易扩展,搭建集群。
4. 较适合于互联网时代多变的数据类型存储。
MongoDB 数据库
1. 安装方式:
(Ubuntu 16)第一种: sudo apt-get install -y mongodb-org
(Ubuntu 18)第二种: sudo apt install mongodb
2. 开启服务:
开启 MongoDB 服务: sudo mongod
第一次开启前需手动创建 MongoDB数据库 保存数据的目录: sudo mkdir -p /data/db (递归创建目录) sudo chmod /data/db 777 (给定权限)
开启 MongoDB shell客户端服务: mongo
3. MongoDB数据库 常用命令
# 查看当前所在数据库
> db
# 查看所有的数据库
> show dbs
# 切换到指定数据库,若切换到不存在数据库不会报错,也无需额外创建数据库、集合,当写入数据时会自动创建
> use youyuan
# 查看当前数据库下所有集合(类似于SQL的table)
> show collections
# 查看当前数据下 指定集合 的所有数据
> db.beijing_mm.find()
# 删除当前数据库下 指定的集合
> db.beijing_mm.drop()
#删除当前数据库
> db.dropDatabase()
4. MongoDB数据库 增删改查,remove默认删除所有,update默认更新一条
a. MongoDB 增加数据 insert() -- python代码实现见 "mongodb_insert.py"
# 第一种: 直接写入一条文档
> db.stu.insert({ "_id" : 1, "name" : "刘备", "age" : 40, "hometown" : "蜀" })
# 第二种: 先创建一个空的文档,依次添加数据,最后统一写入
> data = {}
> data._id = 2
> data.name = "关羽"
> data.age = 38
> data.hometown = "蜀"
> db.stu.inesrt(data)
b. MongoDB 删除数据 remove() -- python代码实现见 "mongodb_remove.py"
1. remove() 默认删除所有符合条件的 文档数据
> db.stu.remove({age : 35})
2. remove() 通过第二个参数 {justOne : true} 来删除第一条符合条件的文档数据
> db.stu.remove({age : 38}, {justOne : true})
3. remove() 通过空的参数,可以删除当前集合下所有文档数据
> db.stu.remove({})
> db.stu.drop() # 删除集合效果相同
4. 在Python中使用: delete_one 和 delete_many
c. MongoDB 修改更新数据 update() -- python代码实现见 "mongodb_update.py"
update至少需提供两个参数: 第一个参数, 匹配的条件; 第二个参数表示, 修改的数据; 第三个参数{multi : true} 表示处理所有文档数据(默认只处理第一条文档)
1. update() 默认将匹配的文档数据,全部替换为 第二个参数的文档数据,但是_id 不变
> db.stu.update({name : "刘备"}, {age : 38, hometown : "蜀国"})
2. update() 通过 $set 修饰符,可以 修改/添加 特定的字段
# 只修改 刘备的 age 为40,并新增gender 为 true
> db.stu.update({name : "刘备"}, {$set : {age : 40, gender : true}})
3. 默认update() 只处理第一条文档,通过 {multi : true} 处理所有文档
> db.stu.update({hometown : "蜀"}, {$set : {gender : true}}, {multi : true})
d. MongoDB 新增+替换 整条文档数据 save()
根据 _id 判断: 如果 _id 已存在,则替换一条文档数据; 如果 _id 不存在, 则新增文档数据。
# _id 不存,新增一条文档数据
> db.stu.save({_id : 2, "name" : "诸葛亮", age : 32, hometown : "蜀", gender : true})
# _id 存在,替换该文档数据
> db.stu.save({_id : 2, "name" : "诸葛孔明", age : 32, hometown : "蜀", gender : true})
e. MongoDB 查询数据 find()
1. 基本查询: 返回所有符合条件的文档数据
> db.stu.find() # 默认返回前20条数据
> db.stu.find({age : 32}).pretty() # 一个字段占据一行的格式输出结果
> db.stu.findOne({age : 32}) # 仅输出一条符合条件的文档数据
2. 比较运算符 : 用来比较数值大小(通用用于比较数字,不建议比较字符串(会比较首字母的ascii值)):
# 默认等于
> db.stu.find({age : 18})
# 大于
> db.stu.find({age : {$gt : 18}})
# 小于
> db.stu.find({age : {$lt : 18}})
# 大于等于
> db.stu.find({age : {$gte : 18}})
# 小于等于
> db.stu.find({age : {$lte : 18}})
# 不等于
> db.stu.find({age : {$ne : 18}})
# 组合使用: 查找age 大于 16 小于等于 40 的文档数据
> db.stu.find({age : {$gt : 16, $lte : 40}})
3. 逻辑运算符 : 用来表示多个条件的 逻辑关系(与 或)
将多个条件 独立,并全部保存在数组中,再通过 与关系$and 或关系$or 修饰
> db.stu.find({age : {$lt : 30}, gender : false}) # 查询年龄小于30 并且 性别女性 的数据
> db.stu.find({$and : [{age : {$lt : 30}}, {gender : false}]}) # 查询年龄小于30 并且 性别女性 的数据
> db.stu.find({$or : [{age : {$lt : 30}}, {gender : false}]}) # 查询年龄小于30 或者 性别女性 的数据
# 1. 找出 age 小雨等于20岁 或 gender 为 false 的文档。 2. 再找出 hometown 为 蒙古
> db.stu.find({$and : [{hometown : "蒙古"}, {$or : [{age : {$lte : 20}}, {gender : false}]} ] })
4. 范围运算符 : 用来判断字段值是否在指定的数据范围内 $in $nin
# 查找 age 值 在 指定数字范围内的文档数据
> db.stu.find({age : {$in : [18, 19, 20, 40]}}) # 查询年龄等于18、19、20、40的数据
# 查找 hometown 值 在 指定数字范围内的文档数据
> db.stu.find({hometown : {$in : ["蒙古", "桃花岛"]}})
# 查找 hometown 值 不在 指定数字范围内的文档数据
> db.stu.find({hometown : {$nin : ["蒙古", "桃花岛"]}})
5. 正则表达式 : 可以通过正则表达式查询结果
# 正则第一种写法: '//' 内包含的是 正则表达式,匹配所有name以 段开头 的文档数据(适合处理中文)
> db.stu.find({name : /^段/})
# 正则第二种写法: {$regex : "正则"} 适合处理英文
> db.stu.find({name : {$regex : "^段"}})
{ "_id" : 8, "name" : "bIgCat", "age" : 18, "hometown" : "汉", "gender" : true }
{ "_id" : 9, "name" : "BigCat", "age" : 18, "hometown" : "汉", "gender" : true }
# 查询 所有name 以 b开头 的文档(且忽略 b 大小写)
> db.stu.find({name : {$regex : "^b", $options : "$i"}})
6. 自定义函数查询 $where : 可以自定义一个 JavaScript函数 执行查询(通常用于补充)
# $where 表示自定义函数执行,会返回集合里的所有符合条件的文档
> db.stu.find({$where : function() {return this.age >= 20}})
# 结果等同于下面语句
> db.stu.find({age : {$gte : 20}})
5. MongoDB 处理查询结果
a. limit() & skip() : limit() 是限定个数输出 ; skip() 是跳过个数再输出。 在一起组合使用时,一定是先 skip() 再 limit()
> db.stu.find().limit(3) # 限定只输出三条文档数据
> db.stu.find().skip(3) # 跳过前三个文档数据,输出后面的数据
> db.stu.find().skip(3).limit(4) # 跳过前三个,限定输出后面的4个
b. 投影输出 : 对文档的特定字段进行处理(显示或不显示)。 在 find() 中添加第二个参数,表示启用投影,可以对字段进行投影处理
# 只显示 name 和 age,其他默认不显示
> db.stu.find({}, {name : 1, age : true})
# 不显示 age 和 gender,其他默认显示
> db.stu.find({}, {age : 0, gender : false})
# 不管是 显示还是不显示, _id 是个特殊的字段,默认都会显示(除非手动指定不显示)
> db.stu.find({}, {age : 1, name :true, _id : false})
注: 显示使用 1/true , 不显示使用 0/false,除_id字段之外不能混合使用0-1/true-false
c. 排序 sort() : 对文档的特定字段进行排序处理(1 为升序, -1 为降序)
# 组合排序:先对age进行升序排序,如果有相同 age值,再按 _id进行降序排序
> db.stu.find({"gender" : true}).sort({age : 1, _id : -1})
注意:在Python代码中,sort将做为 find()方法的参数使用,避免和Python的sort冲突
stu.find({"gender" : True}, sort=[("age", 1), ("_id", -1)])
d. 统计个数 count() : 统计所有查询结果的个数,返回一个数字
# 推荐写法
db.stu.find({gender : true}).count()
# 不建议
db.stu.count({gender : true})
6. MongoDB 索引,普通索引可提高查询效率,唯一索引可用于去重,索引过多会影响数据库写入速度,所以需要进行读写分离
在MongoDB数据库中增加10000条数据: for(i=0;i<1000000;i++) { db.data.insert({_id : i, name : "name"+i, age : i+1})}
1. 查看当前集合下的所有索引
> db.data.getIndexes()
2. 查看find()执行状态(可以统计执行耗时)
> db.data.find({name : "name9527"}).explain("executionStats")
3. 创建索引
> db.data.ensureIndex({name : 1, age : 1})
4. 创建唯一索引 (根据字段创建的唯一索引,如果后续有相同字段值 则无法写入,可用于去重)
> db.data.ensureIndex({"name" : 1}, {"unique":true})
5. 删除索引
#注意:删除索引根据索引名称删除,可以通过 getIndexes() 查询索引名
> db.data.dropIndex("name_1")
7. MongoDB 权限管理
普通模式的MongoDB服务: sudo mongod 这种模式下,任何人都是最高权限
开启权限模式的MongoDB服务: sudo mongod --auth 权限模式下,不同账户指定权限操作数据
1. 开启服务: sudo mongod --auth
2. 创建用户
> use admin
#第一个用户必须是root权限的用户,需要之后通过登录才可以创建其他用户
> db.createUser({uesr : "python", pwd : "123456", roles : ["root"]})
3. 登录到root用户
> use admin
> db.auth("python", "123456")
4. 创建其他用户,并指定权限
> db.createUser({
user : "xiaowang",
pwd : "xiaowang123",
# 对db1 只读权限, db2 有读写权限
roles : [{role : "read", db : "db1"}, {role : "readWrite", db : "db2"}]
})
5. 查看当前MongoDB的所有用户
> use admin
> show users
6. 删除用户(root用户也可以删除自身)
> use admin
> db.dropUser("xiaowang")
8、MongoDB数据库的 备份和恢复(以数据库为单位,处理远程数据库)
1. 备份命令 : 提供参数 -h 被备份的主机ip -d 数据库名 -o 备份到本机的指定目录
> sudo mongodump -h 192.168.28.50 -d movie -o ./
2. 恢复命令: 提供参数 -h 被恢复的主机IP -d 数据库名 --dir 指定备份的数据库目录
> sudo mongorestore -h 192.168.28.55 -d movie --dir ./movie
9、MongoDB数据的 导出和导入(以集合为单位,处理本地数据库)
1. 导出命令 : -d 被导出的数据库 -c 被导出的集合名 -o 导出的文件名 (json、csv)
> sudo mongodexport -d test -c stu -o stu.json
> sudo mongodexport -d test -c stu -o stu.csv --type csv -f _id,name,hometown,age,gender
2. 导入命令 : -d 被导入的数据库 -c 被导入的集合名 --file 需要导入的json文件
> sudo mongoimport -d test -c stu --file stu.json
8、9 通常和Linux的 crontab 定时任务合用。