MySQL、MongoDB、Redis 数据库之间的区别与使用
MySQL、MongoDB、Redis 数据库之间的区别与使用(本章迭代更新)
update:2019年2月20日 15:21:19(本章迭代更新)
一.数据库之间的区别
MySQL
MySQL概述
关系型数据库。无论数据还是索引都存放在硬盘中。到要使用的时候才交换到内存中。能够处理远超过内存总量的数据。
在不同的引擎上有不同 的存储方式。
查询语句是使用传统的 SQL 语句,拥有较为成熟的体系,成熟度很高。
开源数据库的份额在不断增加,MySQL 的份额页在持续增长。
缺点:在海量数据处理的时候效率会显著变慢。
MySQL特点
使用c和c++编写,并使用了多种编译器进行测试,保证源代码的可移植性
支持多种操作系统
为多种编程语言提供可API
支持多线程,充分利用CPU资源优化的SQL查询算法,有效的提高查询速度
提供多语言支持,常见的编码如:GB2312、BIG5、UTF8
提供TCP/IP、ODBC和JDBC等多种数据库连接途径提供用于管理、检查、优化数据库操作的管理工具
大型的数据库。可以处理拥有上千万条记录的大型数据库
支持多种存储引擎
MySQL软件采用了双授权政策,分为社区版和商业版,由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,一般中小型网站的开发都选择MySQL作为网站数据库
MySQL使用标准的SQL数据语言形式
Mysql是可以定制的,采用GPL协议,你可以修改源码来开发自己的MySQL系统
在线DDL更改功能
复制全局事务标识
复制无崩溃从机
复制多线程从机
MongoDB
MongoDB概述
它是一个内存数据库,数据都是放在内存里面的。
对数据的操作大部分都在内存中,但 MongoDB 并不是单纯的内存数据库。
MongoDB 是由 C++ 语言编写的,是一个基于分布式文件存储的开源数据库系统。
在高负载的情况下,添加更多的节点,可以保证服务器性能。
MongoDB 旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。
缺点:占用的空间很大
MongoDB特点
模式自由:可以把不同结构的文档存储在同一个数据库里
面向集合的存储:适合存储JSON风格文件的形式
完整的索引支持,对任何属性可索引
复制和高可用性:支持服务器之间的数据复制,支持主-从模式及服务器之间的相互复制。复制的主要目的是提供冗余及自动故障转移
自动分片:支持水平的数据库集群,可动态添加额外的机器
丰富的查询:支持丰富的查询表达方式,查询指令使用JSON形式额标记,可轻易查询文档中的内嵌的对象及数组
快速就地更新:查询优化器会分析查询表达式,并生成一个高效的查询计划
高效的传统存储方式:支持二进制数据及大型对象
Redis
Redis概述
它就是一个不折不扣的内存数据库。
持久化方式:Redis 所有数据都是放在内存中的,持久化是使用 RDB 方式或者 aof 方式。
Redis特点
Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,在set,hash等数据结构的存储。
Redis支持数据的备份,即master-slave模式的数据备份
性能极高- Redis能读的速度是110000次/s,写的速度是81000次/s
丰富的数据类型-Redis支持二进制案例的Strings,Lists,Hashes,Setes及Ordered Sets数据类型操作。
原子 - Redis的所有操作都是原子性的,同时Redis还支持对几个操作全并后的原子性执行。
丰富的特性 - Redis还支持publish/subscribe,通知,key过期等等特性。
性能区分
* 当物理内存够用的时候,Redis > MongoDB > MySQL
* 当物理内存不够用的时候,Redis 和 MongoDB 都会使用虚拟内存。
实际上如果Redis要开始虚拟内存,那很明显要么加内存条,要么你就该换个数据库了。
但是,MongoDB 不一样,只要,业务上能保证,冷热数据的读写比,使得热数据在物理内存中,mmap 的交换较少。
MongoDB 还是能够保证性能。有人使用 MongoDB 存储了上T的数据。
MySQL,MySQL根本就不需要担心数据量跟内存下的关系。不过,内存的量跟热数据的关系会极大地影响性能表现。
当物理内存和虚拟内存都不够用的时候,估计除了 MySQL 你没什么好选择了。
其实,从数据存储原理来看,更倾向于将 MongoDB 归类为硬盘数据库,但是使用了 mmap 作为加速的手段而已。
使用场景分类
MySQL适用
高度事务性的系统。例如银行或者会计系统,传统的关系型数据库目前还是更实用于需要大量原子性复杂事务的应用程序传统的商业智能应用,针对特定问题的BI数据库会对产生高度优化的查询方式,对于此类应用,数据仓库可能是更合适的选择
MongoDB适用
网站数据:适合实时的插入,更新与查询,并具备网站实时数据存储所需对的复制及高度伸缩性;
缓存:由于性能很高,也适合作为信息基础设施的缓存层,在系统重启之后,搭建的持久化缓存可以避免下层的数据源过载;
大尺寸、低价值的数据也是MongoDB的最佳选择,使用传统的关系数据库存储一些数据时可能会比较贵,再次之前很多程序员往往会选择传统的文件进行存储
高伸缩的场景,非常是个由数十或者数百台服务器组成的数据库
用于对象及json数据的存储,MongoDB的bson数据格式非常适合文档格式化的存储及查询。
Redis适用
用来做缓存-redis的所有数据时放在内存中的
可以在某些特定应用场景下替代传统数据库--比如社交类的应用
在一些大型系统中,巧妙的实现一些特定的功能:session共享、购物车
PS:
MongoDB和Redis都是NoSQL,采用结构型数据存储。二者在使用场景中,存在一定的区别,这也主要由于二者在内存映射的处理过程,持久化的处理方法不同。
MongoDB建议集群部署,更多的考虑到集群方案,Redis更偏重于进程顺序写入,虽然支持集群,也仅限于主-从模式。
简说mmap:
mmap系统调用并不是完全为了用于共享内存而设计的。它本身提供了不同于一般对普通文件的访问方式,进程可以像读写内存一样对普通文件进行操作。
mmap 系统调用使得进程之间通过映射同一个普通文件实现共享内存。普通文件被映射到进程地址空间后,进程可以像访问普通内存一样对文件进行访问,不必再调用。 read(),write()等操作。mmap并不分配空间, 只是将文件映射到调用进程的地址空间里, 然后你就可以用memcpy等操作写文件, 而不用write()了.写完后用msync()同步一下, 你所写的内容就保存到文件里了. 不过这种方式没办法增加文件的长度, 因为要映射的长度在调用mmap()的时候就决定了。
二.安装方式
PS:三种数据库均在Ubuntu中安装(Linux版)
1. 安装MySQL(非常简单)
[root@BenLam-vm_0 ~]# sudo apt-get install mysql-server
[root@BenLam-vm_0 ~]# sudo apt-get isntall mysql-client
[root@BenLam-vm_0 ~]# sudo apt-get install libmysqlclient-dev
2. 安装Mongodb
下载 mongodb 安装包解压文件
[root@BenLam-vm_0 ~]# sudo tar -zxvf 下载目录 -C 解压目录
在解压目录下,新建一个目录data作为数据存储,在data下创建db和log两个目录
# 例如:mongodb所在目录为:/usr/database/mongodb
[root@BenLam-vm_0 ~]# cd /usr/database/mongodb
[root@BenLam-vm_0 ~]# mkdir data
[root@BenLam-vm_0 ~]# cd data
[root@BenLam-vm_0 ~]# mkdir db
[root@BenLam-vm_0 ~]# mkdir log
启动服务器端
# 进入到/mongodb/bin 目录下,执行:
[root@BenLam-vm_0 ~]# sudo ./mongod -dbpath=/usr/database/mongodb/data/db
见到如下信息说明启动成功:
3. 安装Redis
官网地址:http://www.redis.cn/
下载Redis 5.0 安装包解压文件
[root@BenLam-vm_0 ~]# sudo tar -zxvf 下载目录 -C 解压目录
进入解压目录,编译安装 redis
[root@BenLam-vm_0 ~]# sudo make && make install
进入src路径下,启动服务
[root@BenLam-vm_0 ~]# ./redis-server
进入src路径下,启动客户端
[root@BenLam-vm_0 ~]# ./redis-cli
三.数据库日常使用
1. MySQL
2. MongoDB
2.1 MongoDB命令帮助系统
在安装MongoDB后,启动服务器进程(mongod),可以通过在客户端命令mongo实现对MongoDB的管理和监控。看一下MongoDB的命令帮助系统:
[root@BenLam-vm_0 ~]# ./mongod -dbpath=/usr/database/mongodb/data/db
MongoDB shell version: 4.0.6
connecting to: test
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
http://docs.mongodb.org/
Questions? Try the support group
http://groups.google.com/group/mongodb-user
Server has startup warnings:
2018-02-20T23:24:23.304+0000 I CONTROL [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended.
2018-02-20T23:24:23.304+0000 I CONTROL [initandlisten]
2018-02-20T23:24:23.307+0000 I CONTROL [initandlisten]
2018-02-20T23:24:23.307+0000 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.
2018-02-20T23:24:23.307+0000 I CONTROL [initandlisten] ** We suggest setting it to 'never'
2018-02-20T23:24:23.307+0000 I CONTROL [initandlisten]
2018-02-20T23:24:23.307+0000 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2018-02-20T23:24:23.307+0000 I CONTROL [initandlisten] ** We suggest setting it to 'never'
2018-02-20T23:24:23.307+0000 I CONTROL [initandlisten]
> help
db.help() help on db methods
db.mycoll.help() help on collection methods
sh.help() sharding helpers
rs.help() replica set helpers
help admin administrative help
help connect connecting to a db help
help keys key shortcuts
help misc misc things to know
help mr mapreduce
show dbs show database names
show collections show collections in current database
show users show users in current database
show profile show most recent system.profile entries with time >= 1ms
show logs show the accessible logger names
show log [name] prints out the last segment of log in memory, 'global' is default
use set current database
db.foo.find() list objects in collection foo
db.foo.find( { a : 1 } ) list objects in foo where a == 1
it result of the last line evaluated; use to further iterate
DBQuery.shellBatchSize = x set default number of items to display on shell
exit quit the mongo shell
>
这是MongoDB最顶层的命令列表,主要告诉我们管理数据库相关的一些抽象的范畴:数据库操作帮助、集合操作帮助、管理帮助。如果你想了解数据库操作更详细的帮助命令,可以直接使用db.help(),如下所示:
> db.help()
DB methods:
db.adminCommand(nameOrDocument) - switches to 'admin' db, and runs command [ just calls db.runCommand(...) ]
db.auth(username, password)
db.cloneDatabase(fromhost)
db.commandHelp(name) returns the help for the command
db.copyDatabase(fromdb, todb, fromhost)
db.createCollection(name, { size : ..., capped : ..., max : ... } )
db.createUser(userDocument)
db.currentOp() displays currently executing operations in the db
db.dropDatabase()
db.eval() - deprecated
db.fsyncLock() flush data to disk and lock server for backups
db.fsyncUnlock() unlocks server following a db.fsyncLock()
db.getCollection(cname) same as db['cname'] or db.cname
db.getCollectionInfos()
db.getCollectionNames()
db.getLastError() - just returns the err msg string
db.getLastErrorObj() - return full status object
db.getLogComponents()
db.getMongo() get the server connection object
db.getMongo().setSlaveOk() allow queries on a replication slave server
db.getName()
db.getPrevError()
db.getProfilingLevel() - deprecated
db.getProfilingStatus() - returns if profiling is on and slow threshold
db.getReplicationInfo()
db.getSiblingDB(name) get the db at the same server as this one
db.getWriteConcern() - returns the write concern used for any operations on this db, inherited from server object if set
db.hostInfo() get details about the server's host
db.isMaster() check replica primary status
db.killOp(opid) kills the current operation in the db
db.listCommands() lists all the db commands
db.loadServerScripts() loads all the scripts in db.system.js
db.logout()
db.printCollectionStats()
db.printReplicationInfo()
db.printShardingStatus()
db.printSlaveReplicationInfo()
db.dropUser(username)
db.repairDatabase()
db.resetError()
db.runCommand(cmdObj) run a database command. if cmdObj is a string, turns it into { cmdObj : 1 }
db.serverStatus()
db.setLogLevel(level,)
db.setProfilingLevel(level,) 0=off 1=slow 2=all
db.setWriteConcern( ) - sets the write concern for writes to the db
db.unsetWriteConcern( ) - unsets the write concern for writes to the db
db.setVerboseShell(flag) display extra information in shell output
db.shutdownServer()
db.stats()
db.version() current version of the server
2.2 MongoDB基本命令
show dbs
显示当前数据库服务器上的数据库
use pagedb
切换到指定数据库pagedb的上下文,可以在此上下文中管理pagedb数据库以及其中的集合等
show collections
显示数据库中所有的集合(collection)
db.serverStatus()
查看数据库服务器的状态。
有时,通过查看数据库服务器的状态,可以判断数据库是否存在问题,如果有问题,如数据损坏,可以及时执行修复。
查询指定数据库统计信息
use fragment
db.stats()
查询结果示例如下所示:
> use fragment
switched to db fragment
> db.stats()
{
"db" : "fragment",
"collections" : 0,
"objects" : 0,
"avgObjSize" : 0,
"dataSize" : 0,
"storageSize" : 0,
"numExtents" : 0,
"indexes" : 0,
"indexSize" : 0,
"fileSize" : 0,
"ok" : 1
}
查询指定数据库包含的集合名称列表
> db.getCollectionNames()
[
"17u",
"baseSe",
"bytravel",
"daodao",
"go2eu",
"lotour",
"lvping",
"mafengwo",
"sina",
"sohu",
"system.indexes"
]
2.3 基本DDL和DML
创建数据库
> show dbs
local 0.078GB
> use LuceneIndexDB
switched to db LuceneIndexDB
> show dbs
local 0.078GB
> db
LuceneIndexDB
> db.storeCollection.save({'version':'3.5', 'segment':'e3ol6'})
WriteResult({ "nInserted" : 1 })
> show dbs
LuceneIndexDB 0.078GB
local 0.078GB
>
删除数据库
直接使用db.dropDatabase()即可删除数据库。
创建集合
> db.createCollection('replicationColletion', {'capped':true, 'size':10240, 'max':17855200})
{ "ok" : 1 }
> show collections
replicationColletion
storeCollection
system.indexes
删除集合
删除集合,可以执行db.mycoll.drop()。
插入更新记录
> db.storeCollection.save({'version':'0.1', 'segment':'66666'})
WriteResult({ "nInserted" : 1 })
查询一条记录
> db.storeCollection.findOne({'version':'0.1'})
{
"_id" : ObjectId(".........."), # _id 是 MongoDB 自动生成的一段 ObjectId 值
"version" : "0.1",
"segment" : "66666"
}
查询多条记录
使用find()函数,参数指定查询条件,不指定条件则查询全部记录。
8、删除记录
> db.storeCollection.remove({'version':'0.1'})
WriteResult({ "nRemoved" : 2 })
> db.storeCollection.findOne()
null
创建索引
> use pagedb
switched to db pagedb
> db.page.ensureIndex({'title':1, 'url':-1})
{
"createdCollectionAutomatically" : true,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
> db.system.indexes.find()
{ "v" : 1, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "pagedb.page" }
{ "v" : 1, "key" : { "title" : 1, "url" : -1 }, "name" : "title_1_url_-1", "ns" : "pagedb.page" }
查询索引
> db.page.getIndexes()
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "pagedb.page"
},
{
"v" : 1,
"key" : {
"title" : 1,
"url" : -1
},
"name" : "title_1_url_-1",
"ns" : "pagedb.page"
}
]
删除索引
> db.mycoll.dropIndex(name)
2018-01-02T23:45:50.155+0000 E QUERY ReferenceError: name is not defined
at (shell):1:21
> db.mycoll.dropIndexes()
{ "ok" : 0, "errmsg" : "ns not found" }
>
索引重建
> db.page.reIndex()
{
"nIndexesWas" : 2,
"nIndexes" : 2,
"indexes" : [
{
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "pagedb.page"
},
{
"key" : {
"title" : 1,
"url" : -1
},
"name" : "title_1_url_-1",
"ns" : "pagedb.page"
}
],
"ok" : 1
}
统计集合记录数
> use fragment
switched to db fragment
> db.baseSe.count()
36749
查询并统计结果记录数
> use fragment
switched to db fragment
> db.baseSe.find().count()
36749
查询指定数据库的集合当前可用的存储空间
> use fragment
switched to db fragment
> db.baseSe.storageSize()
142564096
查询指定数据库的集合分配的存储空间
> db.baseSe.totalSize()
144096000
2.4 启动与终止
1. 正常启动
[root@BenLam-vm_0 ~]# mongod --dbpath /database --logfile /var/mongo.log
说明:指定数据存储目录和日志目录
如果采用安全认证模式,需要加上--auth选项,如:
[root@BenLam-vm_0 ~]# mongod --auth --dbpath /database --logfile /var/mongo.log
2. 以修复模式启动
[root@BenLam-vm_0 ~]# mongod --repair
以修复模式启动数据库。
实际很可能数据库数据损坏或数据状态不一致,导致无法正常启动MongoDB服务器,根据启动信息可以看到需要进行修复。或者执行:
[root@BenLam-vm_0 ~]# mongod -f /etc/mongodb.conf --repair
3. 终止服务器进程
> db.shutdownServer()
终止数据库服务器进程。或者,可以直接kill掉mongod进程即可。
[root@BenLam-vm_0 ~]# kill your_mongod_services
2.5 备份、恢复与迁移管理
1. 备份全部数据库
[root@BenLam-vm_0 ~]# mkdir testbak
[root@BenLam-vm_0 ~]# cd testbak
[root@BenLam-vm_0 ~]# mongodump
说明:默认备份目录及数据文件格式为./dump/[databasename]/[collectionname].bson
2. 备份指定数据库
[root@BenLam-vm_0 ~]# mongodump -d pagedb
说明:备份数据库pagedb中的数据。
3. 备份一个数据库中的某个集合
[root@BenLam-vm_0 ~]# mongodump -d pagedb -c page
说明:备份数据库pagedb的page集合。
4. 恢复全部数据库
[root@BenLam-vm_0 ~]# cd testbak
[root@BenLam-vm_0 ~]# mongorestore --drop
说明:将备份的所有数据库恢复到数据库,--drop指定恢复数据之前删除原来数据库数据,否则会造成回复后的数据中数据重复。
5. 恢复某个数据库的数据
[root@BenLam-vm_0 ~]# cd testbak
[root@BenLam-vm_0 ~]# mongorestore -d pagedb --drop
说明:将备份的pagedb的数据恢复到数据库。
6. 恢复某个数据库的某个集合的数据
[root@BenLam-vm_0 ~]# cd testbak
[root@BenLam-vm_0 ~]# mongorestore -d pagedb -c page --drop
说明:将备份的pagedb的的page集合的数据恢复到数据库。
3. Redis
3.1 Redis启动
本地启动:redis-cli
远程启动:redis-cli -h host -p port -a password
3.2 Redis连接
验证密码是否正确
AUTH password
打印字符串
ECHO message
查看服务是否运行
PING
关闭当前连接
QUIT
切换到指定的数据库
SELECT index
3.3 Redis keys命令
序列化给定的key并返回序列化的值
DEL key
DUMP key
检查给定的key是否存在
EXISTS key
为key设置过期时间
EXPIRE key seconds
用时间戳的方式给key设置过期时间
EXPIRE key timestamp
设置key的过期时间以毫秒计
PEXPIRE key milliseconds
查找所有符合给定模式的key
KEYS pattern
将当前数据库的key移动到数据库db当中
MOVE key db
移除key的过期时间,key将持久保存
PERSIST key
以毫秒为单位返回key的剩余过期时间
PTTL key
以秒为单位,返回给定key的剩余生存时间
TTL key
从当前数据库中随机返回一个key
RANDOMKEY
修改key的名称
RENAME key newkey
仅当newkey不存在时,将key改名为newkey
RENAMENX key newkey
返回key所存储的值的类型
TYPE key
3.4 Reids字符串命令
SET key value
GET key
GETRANGE key start end
返回key中字符串值的子字符
GETSET key value
将给定key的值设为value,并返回key的旧值
GETBIT KEY OFFSET
对key所储存的字符串值,获取指定偏移量上的位
MGET KEY1 KEY2
获取一个或者多个给定key的值
SETBIT KEY OFFSET VALUE
对key所是存储的字符串值,设置或清除指定偏移量上的位
SETEX key seconds value
将值 value 关联到 key ,并将 key 的过期时间设为 seconds (以秒为单位)。
SETNX key value
只有在 key 不存在时设置 key 的值。
SETRANGE key offset value
用 value 参数覆写给定 key 所储存的字符串值,从偏移量 offset 开始。
STRLEN key
返回 key 所储存的字符串值的长度。
MSET key value [key value ...]
同时设置一个或多个 key-value 对。
MSETNX key value [key value ...]
同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在。
PSETEX key milliseconds value
这个命令和 SETEX 命令相似,但它以毫秒为单位设置 key 的生存时间,而不是像 SETEX 命令那样,以秒为单位。
INCR key
将 key 中储存的数字值增一。
INCRBY key increment
将 key 所储存的值加上给定的增量值(increment)。
INCRBYFLOAT key increment
将 key 所储存的值加上给定的浮点增量值(increment)。
DECR key
将 key 中储存的数字值减一。
DECRBY key decrement
key 所储存的值减去给定的减量值(decrement)。
APPEND key value
如果 key 已经存在并且是一个字符串, APPEND 命令将 指定value 追加到改 key 原来的值(value)的末尾。