一文读懂MongoDB

问:内部的存储结构?

答:bson

问:为什么mongodb会选择bson,bjson与json有什么区别?

答:首先json比较普遍,其次bson的效率由于json,(1)类似于redis的len字段,bson会把每个元素的len字段存在头部,优化了遍历速度,读取数据的时候可以直接跳到该元素那里进行读取(2)对json来说操作是无类型的,9和10的性能是不一样的一个字符和两个字符的区别,但是buson不会,类似于redis的整数型数据类型,长度不变,只是改变了值

问:怎么实现事务的

答:MongoDB3.0支持单文档事务,基于WiredTiger引擎,保证数据,索引,oplog三者的原子性

问:MongoDB实现事务的难点在于时序问题

答:MongoDB 通过 oplog 时间戳来标识全局顺序,而 WiredTiger 通过内部的事务ID来标识全局顺序,在实现上,2者没有任何关联。这就导致在并发情况下, MongoDB 看到的事务提交顺序与 WiredTiger 看到的事务提交顺序不一致。这种情况下,MongoDB4.0中WiredTiger只能做调整,加入时间戳transaction timestamp;

在 3.x 版本里,一个写请求对数据、索引、oplog的修改会放到一个 WT 事务里,事务的提交由 MongoDB 自己控制,MongoDB 会尽可能快的提交事务,完成写清求;但 4.0 引入事务之后,事务的提交由应用程序控制,可能出现一个事务修改很多,并且很长时间不提交,这会给 WT cache evict 造成很大的影响,如果大量内存无法 evict,最终就会进入 cache stuck 状态。为了尽量减小 WT cache 压力,MongoDB 4.0 事务功能有一些限制,但事务资源占用超过一定阈值时,会自动 abort 来释放资源。

问:一个事务中文档数可以非常大吗?一个事务操作最大允许时间是多大?

答:(1)事务的生命周期不能超过 transactionLifetimeLimitSeconds (默认60s),该配置可在线修改,(2)事务修改的文档数不能超过 1000 ,不可修改

问:事务如何回滚?

答:在 3.x 版本里,MongoDB 的节点需要回滚时,会根据要回滚的 oplog 不断应用相反的操作,或从回滚源上读取最新的版本,整个回滚操作效率很低。

4.0 版本实现了存储引擎层的回滚机制,当复制集节点需要回滚时,直接调用 WiredTiger 接口,将数据回滚到某个稳定版本(实际上就是一个 Checkpoint),这个稳定版本则依赖于 stable timestamp。WiredTiger 会确保 stable timestamp 之后的数据不会写到 Checkpoint里。

问:MongoDB持久化策略?

答:在MongoDB启动的时候,会开启一个线程去循环将数据写入磁盘,但是写的方式是有一定时间周期,异步延迟去写

问:mongodb的存储引擎是什么?

答:MongoDB目前支持的存储引擎为内存映射引擎。当MongoDB启动的时候,会将所有的数据文件映射到内存中,然后操作系统会托管所有的磁盘操作。这种存储引擎有以下几种特点:

* MongoDB中关于内存管理的代码非常精简,毕竟相关的工作已经有操作系统进行托管。

* MongoDB服务器使用的虚拟内存将非常巨大,并将超过整个数据文件的大小。不用担心,操作系统会去处理这一切。

问:为什么mongodb是面向集合的?自由的?文档型?

答:面向集合:数据被分组到若干集合,这些集合称作聚集(collections);

自由的:数据库并不需要知道你将存入到聚集中的文档的任何结构信息.实际上,你可以在同一个聚集中存储不同结构的文档

文档型:我们存储的数据是键-值对的集合,键是字符串,值可以是数据类型集合里的任意类型,包括数组和文档. 我们把这个数据格式称作bson,可以存照片和视频;

面向文档的数据库用一个有组织的文件来存储数据,而不是用行来存储数据,在MongoDB中,一组文档被看作是一个集合,在关系数据库中,许多行的集合被看作是一张表。

像上面的一个结构,为一个文档(document),相当于关系数据库中的一行记录,多个文档组成一个集合(collection),相当于关系数据库的表。多个集合(collection),逻辑上组织在一起,就是数据库(database),一个MongoDB实例支持多个数据库(database)。

问:mongodb的设计有很多缺点,譬如?

答:(1)在32位系统上,不支持大于2.5G的数据

(2)单个文档大小限制为 4 M/16 M(1.8版本后升为16M)

(3)对内存要求比较大

(4)用户权限方面比较弱,这一点MongoDB官方推荐的是将机器部署在安全的内网环境中,尽量不要用权限

Wordnik:从MySQL到MongoDB:

https://blog.csdn.net/hzcyclone/article/details/7304293

问:mongodb的数据存在内存还是磁盘?

答:热点数据存在内存,其它数据存在磁盘,利用内存映射引擎做关联

问:单机的情况下为什么不建议用mongodb?

答:因为mongodb的持久化做的不好,宕机的时候会丢失一部分数据,因为持久化策略是延后一段时间写入磁盘

问:对于文档这种东西的存储如何更好地白话理解?

答:面向文档,那么什么是文档呢?很明显这不是我们常见的word文档。这里说的文档,是一种可以嵌套的数据集合。从关系数据库的范式的概念来说,嵌套是明显的反范式设计。范式设计的好处是消除了依赖,但是增加了关联,查询需要通过关联两张或者多张表来获得所需要的全部数据,但是更改操作是原子的,只需要修改一个地方即可。反范式则是增加了数据冗余来提升查询性能,但更新操作可能需要更新冗余的多处数据,需要注意一致性的问题。

一个典型的例子,如blog,关系数据库中一般可以把文章设计为一张表,评论设计为一张表,那么在页面需要展示一篇文章和其对应的评论的时候,就需要关联查询文章表和评论表。但是面向文档的设计,可以将评论作为文章的一个嵌套文档存放在一起,这不但省去了关联查询,由于存储在一起,查询的性能也可以做到更好。

MongoDB的面向文档采用的是BSON,一种类似JSON的格式,但是是二进制序列化的。如上面提到的blog的文章和评论,可以做如下设计:

{ 'id':1, 'author':'NinGoo', 'title':'白话MongoDB(一)', 'content':'按照官方的说法,此处省略一万字',

    comment:[ {'comment-author':'宋兵甲', 'comment-content':'有木有' } ,

              {'comment-author':'尼玛','comment-content':'伤不起啊' }

            ]

}

问:数据量过大超过16M,需要用到mongodb底层的GridFS直接作为文件存储,什么是GridFS?

答:

问:Modifier是什么?

答:Modifier也是MongoDB可以作为对用户行为跟踪的容器。在实际中使用Modifier来将用户的交互行为快速保存到MongoDB中以便后期进行统计分析和个性化定制。

问:Map/Reduce

Map/Reduce也是MongoDB中比较吸引人的特性。Map/Reduce可以对大数据量的表进行统计、分类、合并的工作,完成原先SQL的GroupBy等聚合函数的功能。并且Mapper和Reducer的定义都是用Javascript来定义服务端脚本。

问:mmap机制是什么?

答:MongoDB由于采用了mmap机制,如果索引和热数据能被内存完全装下,那么其操作基本上相当于内存操作,所以MongoDB的当机性能是相当高的。

问:mongodb支持关联查询码?

答:MongoDB提供与关系型数据库类似的各种数据操作(除了关联查询),其索引机制更是与关系型数据库几乎一模一样。同时MongoDB也提供MapReduce的操作接口,用以处理一些批量任务。

MySQL和MongoDB设计实例对比

本文转载自火丁笔记,文章举了一个数据库设计的例子,对MySQL和MongoDB两种存储工具,分别进行了数据库结构设计,在MongoDB的设计上,利用了MongoDB的 schema-free的特性。

虽然文中的例子不一定是最优的选择。但分享此文,希望提醒大家,换个存储,不仅是换一个存储,更重要的是换一套思维。

MySQL是关系型数据库中的明星,MongoDB是文档型数据库中的翘楚。下面通过一个设计实例对比一下二者:假设我们正在维护一个手机产品库,里面除了包含手机的名称,品牌等基本信息,还包含了待机时间,外观设计等参数信息,应该如何存取数据呢?

如果使用MySQL的话,应该如何存取数据呢?

如果使用MySQL话,手机的基本信息单独是一个表,另外由于不同手机的参数信息差异很大,所以还需要一个参数表来单独保存。

CREATE TABLE IF NOT EXISTS `mobiles` (

    `id` int(10) unsigned NOT NULL AUTO_INCREMENT,

    `name` VARCHAR(100) NOT NULL,

    `brand` VARCHAR(100) NOT NULL,

    PRIMARY KEY (`id`)

);

CREATE TABLE IF NOT EXISTS `mobile_params` (

    `id` int(10) unsigned NOT NULL AUTO_INCREMENT,

    `mobile_id` int(10) unsigned NOT NULL,

    `name` varchar(100) NOT NULL,

    `value` varchar(100) NOT NULL,

    PRIMARY KEY (`id`)

);
INSERT INTO `mobiles` (`id`, `name`, `brand`) VALUES

(1, 'ME525', '摩托罗拉'),

(2, 'E7'   , '诺基亚');

INSERT INTO `mobile_params` (`id`, `mobile_id`, `name`, `value`) VALUES

(1, 1, '待机时间', '200'),

(2, 1, '外观设计', '直板'),

(3, 2, '待机时间', '500'),

(4, 2, '外观设计', '滑盖');

注:为了演示方便,没有严格遵守关系型数据库的范式设计。

如果想查询待机时间大于100小时,并且外观设计是直板的手机,需按照如下方式查询:

SELECT * FROM `mobile_params` WHERE name = '待机时间' AND value > 100;

SELECT * FROM `mobile_params` WHERE name = '外观设计' AND value = '直板';

注:参数表为了方便,把数值和字符串统一保存成字符串,实际使用时,MySQL允许在字符串类型的字段上进行数值类型的查询,只是需要进行类型转换,多少会影响一点性能。

两条SQL的结果取交集得到想要的MOBILE_IDS,再到mobiles表查询即可:

SELECT * FROM `mobiles` WHERE mobile_id IN (MOBILE_IDS)

如果使用MongoDB的话,应该如何存取数据呢?

如果使用MongoDB的话,虽然理论上可以采用和MySQL一样的设计方案,但那样的话就显得无趣了,没有发挥出MongoDB作为文档型数据库的优点,实际上使用MongoDB的话,和MySQL相比,形象一点来说,可以合二为一:

db.getCollection("mobiles").ensureIndex({

    "params.name": 1,

    "params.value": 1

});

db.getCollection("mobiles").insert({

    "_id": 1,

    "name": "ME525",

    "brand": "摩托罗拉",

    "params": [

        {"name": "待机时间", "value": 200},

        {"name": "外观设计", "value": "直板"}

    ]

});

db.getCollection("mobiles").insert({

    "_id": 2,

    "name": "E7",

    "brand": "诺基亚",

    "params": [

        {"name": "待机时间", "value": 500},

        {"name": "外观设计", "value": "滑盖"}

    ]

});

如果想查询待机时间大于100小时,并且外观设计是直板的手机,需按照如下方式查询:

db.getCollection("mobiles").find({

    "params": {

        $all: [

            {$elemMatch: {"name": "待机时间", "value": {$gt: 100}}},

            {$elemMatch: {"name": "外观设计", "value": "直板"}}

        ]

    }

});

注:查询中用到的$all,$elemMatch等高级用法的详细介绍请参考官方文档中相关说明。

MySQL需要多个表,多次查询才能搞定的问题,MongoDB只需要一个表,一次查询就能搞定,对比完成,相对MySQL而言,MongoDB显得更胜一筹,至少本例如此。

问:ACID与BASE和区别?

答: 理解ACID与BASE的区别(ACID是关系型数据库强一致性的四个要求,而BASE是NoSQL数据库通常对可用性及一致性的弱要求原则,它们的意思分别是,ACID:atomicity, consistency, isolation, durability;BASE:BasicallyAvailable, Soft-state, Eventually Consistent。同时有意思的是ACID在英语里意为酸,BASE意思为碱)

 

你可能感兴趣的:(分布式)