本文地址:https://www.askmac.cn/archives/overview-mongodb.html
在本连载中我们会对mongodb有一个初步的认识,介绍在何种场景下mongodb是适用的。
NOSQL
在过去20年间,CPU的处理能力上升了几十倍,而同样空间的磁盘的成本也下降到了原来的千分之一。越来越多的开发工程针对web端和移动app而存在,而我们的计算机环境软硬件造就了我们今天所能处理的数据量和互联网的访问量都成倍增长了;由于对于数据存放和处理的数据库环境也在逐渐进化。
在传统的RDBMS关系型数据库中,对于担当极高流量的web系统的后台数据库而言,集中式非分片化的架构逐渐显现出了性能的极限。 所以目前正流行着通过在适当的位置以NOSQL来补充,以便补足原有系统在性能上的不足。
NOSQL的分类
KVS(Key-Value Store)
该类型将数据以key/value =>HASH的形式来存放,一般使用完全一致的key搜索来取得数据,实现高速运行, 代表性的产品是:Memcached,Redis等
文档指向数据库
不定义schema也能使用的数据库,标榜Schema-less,可以使用复杂的查询条件获得数据,代表产品是:mongoDB和CouchDB等
列存数据库
Cassandra使用了Google 设计的 BigTable的数据模型,与面向行(row)的传统的关係型资料库或键值存储的key-value资料库不同,Cassandra使用的是宽列存储模型(Wide Column Stores)[2],每行数据由row key唯一标识之后,可以有最多20亿个列[5],每个列由一个column key标识,每个column key下对应若干value。这种模型可以理解为是一个二维的key-value存储,即整个数据模型被定义成一个类似map<key1, map<key2,value>>的类型。 与Cassandra类似的产品还有 Hbase。
MongoDB的目标
MongoDB 是一种 文档指向的NOSQL数据库,继承了NOSQL的高性能和可拓展性,又兼具RDBMS的部分必要功能,在2者之间获得了较好的平衡。 key value store的NOSQL放弃了大量传统RDBMS的功能,而获得了更佳的性能。 但是反过来说key value store也丢失了大量有意义的功能。特别是当大量的开发和维护人员已经习惯了这些RDBMS的基本功能的时候。 如果要讨论MongoDB,那么一样的也要了解其自身限制,如此才可能在合适的场景中充分利用其特性。
与传统RDBMS相比 MongoDB不提供事务(transaction)和JOIN连接。这2个核心功能随着你的应用场景的不同,有些场景中可能你完全可以接受没有事务和JOIN;而有些场景(考虑 银行转账、对账业务如果没有事务会是什么鸟样)。 MongoDB舍弃事务(transaction)和JOIN连接的原因是,如果要在复杂的分片环境中实现这2个功能的话,其性能成本会非常高,为了实现这2个功能如果把NOSQL原本应当由的高性能特点搞没了的话,那么就得不偿失了。 另一方面,通过不支持transaction,那么开发者也就不用为deadlock死锁之类的问题而考虑,让系统更纯粹、简单明了。 总之MongoDB为了追求成为轻量告诉的数据库的目标,于是舍弃了事务(transaction)和JOIN连接这2个传统RDBMS的代表性功能。
对比KVS和mongodb的功能, 例如KVS中的memcached基本职能救援key进行完全一致的搜索,而在mongodb中却可以利用类似RDBMS中的where、like的操作符做复杂的数据查询搜索。另外MongoDB 2.2开始增加了统计处理的功能,可以使用sum、avg或 相当于的group by , having, order by的查询组合。
除了上述功能外mongodb还有安装简单的特性,mongoDB提供在主流操作系统上的各类形式安装包,以及大量主流开发语言的驱动程序;与KVS相比其接口更多。 即MongoDB做了大量亲民的工作,希望用户很快能上手。
MongoDB的思想
为了介绍MongoDB的思想,我们这里引用MongoDB联合创始人兼CTO Eliot Horowitz的话:
MongoDB并不是在实验室中涉及出来的, 我们基于过往对构筑坚固、高可收缩性、高可用性系统的经验,开发出了MongoDB。所以它并不是从0开始的。
关于MongoDB我是这样考虑的,如果将MySQL的关系型模型向Document文档模型转变,让管理文档简单快速,使用Schema-less的数据库模型和agile的开发手法, JOIN将变得不再重要,而scale-out横向扩展将变得简单得多, 由此我们可以得到很多很棒的功能。
RDBMS关系型数据库中,有着最丰富的特性,例如 index索引、动态查询以及完善的备份恢复功能等等,举止不尽。 mongodb也引入了大量的特性,例如mongodb中索引的使用很类似于mysql和oracle中的索引。 基于这些思想,mongodb才能发展至今。
MongoDB的特征
mongodb即是schema-less(现在更多叫做dynamic schema了),又是面向文档的数据库 , 同时mongodb具有复制功能和自动故障转移failover的能力,基于Replica Set。 有着范围分区功能和自动平衡数据的能力,即sharding。
与RDBMS相比 , 读写性能较高
通过对transaction和关系模型的不支持, 其可以提供接近于KVS key value store的性能。
开发环境简单方便
为了能在任何环境都能发挥最佳性能,MongoDB研发人员提供了各种主流语言上的原生socket协议驱动。 提供了标准的REST借口。可以使用于web中广泛应用的JSON数据的收发。
如何把mongodb的特性用好
一个例子是在网站的访问/操作日志应用上使用MongoDB,这种例子已经很常见了。由于应用输出的日志格式可能十分灵活,因此在这里schema-less可以很好发挥作用。
用户也可以开发其他类型的应用例如问卷调差系统,由于schema-less的存放,可以很变通地处理多变的数据结构。 以后对独立的各个field字段做搜索也很容易。
MongoDB很使用那些有大量轻量级读写处理的网络/社交游戏, 因为有很好的可扩展性和复制Replication功能。
但是如果是下面的场景,那么就要多加考虑是否适用MongoDB了
银行或会记行业的系统,主要负责对账或交易的系统。 由于mongodb不支持事务transaction,而上述系统中大量的业务是强事务类型的。
对于必须是使用SQL的环境而言,由于MongoDB是不支持SQL的,所以不可能在这里使用MongoDB。
MongoDB的安装和使用例子
mongodb 3.0.2在ubuntu上安装的文档:https://www.askmac.cn/archives/upgrade-to-mongodb-302-wiredtiger.html
mongoDB连接数据库
mongodb中不需要像MySQL里那样手动创建数据库create database操作, 需要创建一个尚未创建的数据库时直接使用 use DB_NAME; 命令 并对应的在该数据库中插入一个document到一个collection计算创建数据库了。
macpro:~ maclean$ mongo MongoDB shell version: 3.0.2 connecting to: test > use dbdao_test1; > db.c1.insert({date1:Date()}); WriteResult({ "nInserted" : 1 }) > db.c1.find(); { "_id" : ObjectId("55d9bbe9919270dad8d26892"), "date1" : "Sun Aug 23 2015 20:26:17 GMT+0800 (CST)" } > show dbs Northwind 0.078GB admin 0.078GB dbdao_test1 0.078GB local 0.078GB reporting 1.953GB test 0.203GB
插入document到一个collection
可以利用如下语句插入一个document 到 名为testcoll的collection中,
db.testcoll.insert({"key1":"string","key2":123});
如果没有提示任何错误的话 就意味着插入成功了。
与普通的关系型数据库的SQL插入有较大差别 insert values, 其中 “db.testcoll.insert()” , 其中”db“指代当前数据库, “db.testcoll” 即指代当前数据库中的testcoll这个collection集合。 后面的insert是要调用的方法,即插入方法。
然后是插入的document {“key1″:”string”,”key2″:123} , 这是JSON形式的数据,我们省略JSON的说明,但是对于MongoDB的操作研二,基本都会用到JSON形式的数据来处理。
db.testcoll.insert ({ "array":[ "sun","mon","tue" ]});
document文档的查询
文档查询的基本方法是find()函数,例如下面的例子:
> db.testcoll.find(); { "_id" : ObjectId("55d9bd78919270dad8d26893"), "key1" : "string", "key2" : 123 } { "_id" : ObjectId("55d9c07e919270dad8d26895"), "array" : [ "sun", "mon", "tue" ] }
可以通过findOne()函数来仅仅获得一个document:
> db.testcoll.findOne(); { "_id" : ObjectId("55d9bd78919270dad8d26893"), "key1" : "string", "key2" : 123 }
Leave a Reply