python与mongodb
一、mongodb的原理介绍:
特点:
为了理解以上特点,我们从一个真实的场景出发,介绍mongodb的原理:参考视频:https://www.youtube.com/watch?v=4SxHNmk5JHI
我们需要从华为的app商店里抓取一些app的详细信息的数据;如下图,这是我们爬到的一条数据,是一条关于微信的详细信息数据:
实际上,我们每次抓取一条这样的信息,我们可以称为一个document。这也是所谓的基于document的设计。
当然了,问题是如何保存我们这样的数据,或是说documents呢?最基本的是存在文件里。
我们假如蓝色区域是我们的文件,每个document顺序地存在文件中,比如第一个是关于微信信息的一个document。
但是,问题出来了,当我们顺序存储之后,当微博出了一个新的版本“5.7.0”,我们怎么把这样的信息添加到微博的那个document中呢?
由于数据是连续的存在硬盘中,我们可以把原来微博的那个document的信息copy下来,然后在顺序添加一个含有版本信息“5.7.0”的document。如下图:
之后,我们再把第二个document删掉。
但是这种方法有个问题,当我们在遍历的时候,中间出现很多gaps,从而带来读取写入的低效。如下图:
一个讨巧的方法就是,我们建立一个指针,也就是每个document都存一个指针,指向下一个document的位置。这样读取的时候就可以读取下一个document。
同理,我们也可以建立反向指针,如下图:
好,刚才我们说的是出现这些fragment或是gaps时候怎么能够读取的更快。
那我们有没有方法能减少这些碎片呢?
减少碎片,也就是比如我们在修改微博的信息的时候尽量减少这些“document”快的移动,方法就是加"pading",也就是在每个document后边都预留一块空白的pading,
如下图:
当我们有新得数据需要添加的时候,就可以添加到pading里,从而能够保证不用迁移整块数据:
那么,既然我们知道怎么保存这些document到文件中,下面我们看下怎么保存到硬盘上:
如上图,我们的硬盘上已经有一些文件,我们的新文件只能零散地存在夹缝之中,又造成了很多碎片,这是另外一种碎片。
导致读取的时候不能顺序读取,造成了很多随机寻道的事件,造成了低效率。
How to reduce this fragments?
有一种方法,就是我们提前预先申请好一块大的空间。能保证连续的保存很多文件。
那么,如何选择预先申请的空间大小。小的话也会出现碎片,大的话会浪费。
我们的方法是double上升,也就是我们从最近本的16M开始,16M写满了申请一个32M的,写满了再申请一个64M的,128M...2G,不能无限上升,即最大为2G的,以后再申请就是2G的。如下图:
现在,写的问题解决了,我们需要面临读的问题。
即,我们怎么查找ID在这个区间的所有的document呢?
大家,如果做过的话,我们都知道,最基本的方法是用一个二叉搜索树,因为遍历和插入复杂度为log(n),每个树的节点左侧是比它数小的节点的集合,右侧是比它大的节点的ID结合。这种方法不断的扩展。每个节点位置,都存放一个指针,指向在硬盘上存储的位置,如下图。当然,在实际使用中,我们会使用二叉搜索树的升级版:Btree。
ok ,当目前为止,你已经实现了Mongodb。你已经知道mongodb长什么样,以及为啥这样?’
我们再看开头说的mongodb的特点:
第一,document的属性都可以随意修改。即上图的小绿色条,大小和内容都可以不一样
其次,添加padings。避免document快的移动增加的碎片。第三,添加双向指针,提高效率。
第四,mongodb硬盘的保存过程中实际上保存在。document保存在2上升的硬盘上。最后,Btree的方式建立索引,提高查找的效率。
二、python操纵mongodb
参考PyMongo - MongoDB API,https://api.mongodb.com/python/current/。