详解MongoDB BSON格式的问题讲解
问题1:字符串与数字
{a:12}
{a:'12'}
哪个更占空间?
{a:1234}
{a:'1256'}
又是哪个更占空间?
对于第一个例子,应该是前一个更占空间,而对于第二个例子,是后一个更占空间。具体原因是:MongoDB对数字的存储分两个级别,一个32位的,一是64位的,如我们上面的例子,都是在32位能表达的范围内,所以数字型的占用4个字节,而字符串型的占用空间为其长度加上最后一位结束符。所以第一个例子中字符串占用3个字节,第二个例子中字符串占用5个字节。
同样的,在索引里也是一样,不过值得注意的是,字符串与数字在排序方式上不一样,所以在索引时,数字是按数字的方式比对大小,字符串是按字符串的方式比对大小,比如在字符串中,’12′是小于’2′的。
问题2:对象与数组
哪个更占空间?
可能你会觉得是第一个,因为它看起来长度更长,或者你还会觉得是因为它包含了每个字段的key值。而实际上呢?
答案是第二个会占用更多空间,因为BSON数据结构在存储数组类型时,是与对象类似的方法,比如第二条的存储实际上相当于这样:
以下是引用片段:
{d:{0:1,1:2,2:3}}
问题3:_id与$natural的排序
MongoDB中有一个特殊的排序方法,叫$natural,当你指定按$natural排序的时候,相当于是按数据在磁盘上的组织顺序排序。而当你按自动生成的_id字段排序时,相当于是按插入时间排序。当不指定排序顺序的时候,MongoDB是按$natural排序的。这两个有什么差别吗?插入顺序与数据组织顺序不应该一样吗?答案是:有可能。
当MongoDB中的数据有变更时,可能会导致数据的移动,比如你先用下面的方式写入1000条数据:
以下是引用片段:
for(var i=0;i<1000;i++)db.test.insert({_id:i,a:'1'})
然后你分别使用下面命令按_id和$natural排序取出前一条结果:
以下是引用片段:
db.test.find().sort({_id:1}).limit(1)
db.test.find().sort({$natural:1}).limit(1)
你得到的结果会是一样的。
这时候你进行一次update操作,将第一条记录的长度变长:
以下是引用片段:
db.test.update({},{a:'12'})
然后你再将第一条记录变长:
以下是引用片段:
db.test.update({},{a:'123'})
再通过上面两种不同的排序方式取第一条,这时候你会看到,通过_id排序查到的还是原来那一条,而通过$natural查到的已经变成了第二条。这是什么原因呢?
当我们执行insert操作的时候,每条记录的长度为31,你可以通过下面命令查看到。
以下是引用片段:
Object.bsonsize(db.test.findOne());
而当我们通过一次update,将a值变为’12′时,其长度变长了1字节,变成了32。当我们又一次将a值变为’123′时,其长度变成了33。那为什么记录长度从31到32的时候,按$natural查到的第一条还是原来的,但是长度从32变到33的时候,通过$natural查到的就变了呢?
先说为什么变了,因为MongoDB在记录长度变化后,发现当前记录所在空间后面没有空余的空间可供其变长。那么这条记录就会被删除然后移动到数据集的最后。这是为什么第二次我们通过$natural查到的第一条不是原来那条的原因。因为原来那条已经跑到最尾巴上去了。
但是为什么第一次增长长度时记录没有移动呢?可能你从数字31,32,33上已经看出点端倪来了。对,就是内存对齐,MongoDB每一条记录都会做4字节的内存对齐。所以在你刚插入的时候,记录长度虽然只有31字节,但是MongoDB会为它分配32字节(8*4)的空间。这时候在其末尾就有一字节的空闲,当你增长一字节的时候,这一字节的空闲正好可以用上。所以就不需要移动位置了。而第二次从32字节变成33字节,原有的空间已经不能装下了,所以会造成数据的移动。实际上4字节对齐,也同时造成一些空间的浪费。同时引起数据变长后移动上的不确定性。
相关热词:
本站内容来源于网络,如有侵权请与我们联系,我们会及时删除,我们深感抱歉!
注:本站所有信息仅供用于网络技术学习参考,学习中请遵循相关法律法规!
本文地址: https://v30.fanwenzhu.com/sql/db2/11804.shtml
相关文章
热门TAG
win10 ecshop 主机 阿里云 解决 配置 C# C++ 解析 SQL语句 命令 Go语言 方法 CSS3 HTML5 CSS win7 MSSQL 服务器配置 IIS7.5 IIS7 IIS6 IIS CentOS 7 Linux oracle数据库 oracle phpcms discuz discuz教程最新文章
-
数据库(MSSQLServer,Oracle,DB
时间:2021-01-17
-
这样不容易出错
时间:2021-01-17
-
管理客户端从v9.7版本之后
时间:2021-01-17
-
3.3、点击Apply完成合并
时间:2021-01-17
-
用hbase存储所有的时序(无
时间:2021-01-13
-
图6 使用对象浏览器上的
时间:2021-01-13
-
还是建议大家安装要求来
时间:2021-01-13
-
Set) ExecuteScalar():从数
时间:2021-01-13
热门文章
-
还是建议大家安装要求来
时间:2021-01-13
-
数据库(MSSQLServer,Oracle,DB2,MySql)常见语句以
时间:2021-01-17
-
那么SQL执行计划都会被执行; ⑤ 6.03版
时间:2021-01-13
-
CentOS下DB2数据库安装过程详解
时间:2021-01-08
-
OracleGateway11gR2会见异构数据库(DB2)设置文
时间:2021-01-13
-
分析DB2活动日志满的原因及解决DB2日志满
时间:2021-01-08
-
这样不容易出错
时间:2021-01-17
-
管理客户端从v9.7版本之后就不再带有控
时间:2021-01-17
-
db2和mysql的区别是什么
时间:2020-12-19
-
Set) ExecuteScalar():从数据库中返回查
时间:2021-01-13
