写点什么

为什么 MongoDB 使用 B 树(二)

  • 2019-12-26
  • 本文字数:1632 字

    阅读完需:约 5 分钟

为什么 MongoDB 使用 B 树(二)

非关系型

我们在上面其实已经多次提到了 MongoDB 是非关系型的文档数据库,它完全抛弃了关系型数据库那一套体系之后,在设计和实现上就非常自由,它不再需要遵循 SQL 和关系型数据库的体系,可以更自由对特定场景进行优化,而在 MongoDB 假设的场景中遍历数据并不是常见的需求。



MySQL 中使用 B+ 树是因为 B+ 树只有叶节点会存储数据,将树中的每一个叶节点通过指针连接起来就能实现顺序遍历,而遍历数据在关系型数据库中非常常见,所以这么选择是完全没有问题的7


MongoDB 和 MySQL 在多个不同数据结构之间选择的最终目的就是减少查询需要的随机 IO 次数,MySQL 认为遍历数据的查询是常见的,所以它选择 B+ 树作为底层数据结构,而舍弃了通过非叶节点存储数据这一特性,但是 MongoDB 面对的问题就不太一样了:



虽然遍历数据的查询是相对常见的,但是 MongoDB 认为查询单个数据记录远比遍历数据更加常见,由于 B 树的非叶结点也可以存储数据,所以查询一条数据所需要的平均随机 IO 次数会比 B+ 树少,使用 B 树的 MongoDB 在类似场景中的查询速度就会比 MySQL 快。这里并不是说 MongoDB 并不能对数据进行遍历,我们在 MongoDB 中也可以使用范围来查询一批满足对应条件的记录,只是需要的时间会比 MySQL 长一些。


SQL


SELECT * FROM comments WHERE created_at > '2019-01-01'
复制代码


很多人看到遍历数据的查询想到的可能都是如上所示的范围查询,然而在关系型数据库中更常见的其实是如下所示的 SQL —— 查询外键或者某字段等于某一个值的全部记录:


SQL


SELECT * FROM comments WHERE post_id = 1
复制代码


上述查询其实并不是范围查询,它没有使用 >< 等表达式,但是它却会在 comments 表中查询一系列的记录,如果 comments 表上有索引 post_id,那么这个查询可能就会在索引中遍历相应索引,找到满足条件的 comment,这种查询也会受益于 MySQL B+ 树相互连接的叶节点,因为它能减少磁盘的随机 IO 次数。


MongoDB 作为非关系型的数据库,它从集合的设计上就使用了完全不同的方法,如果我们仍然使用传统的关系型数据库的表设计思路来思考 MongoDB 中集合的设计,写出类似如上所示的查询会带来相对比较差的性能:


JavaScript


db.comments.find( { post_id: 1 } )
复制代码


因为 B 树的所有节点都能存储数据,各个连续的节点之间没有很好的办法通过指针相连,所以上述查询在 B 树中性能会比 B+ 树差很多,但是这并不是一个 MongoDB 中推荐的设计方法,更合适的做法其实是使用嵌入文档,将 post 和属于它的所有 comments 都存储到一起:


JSON


{    "_id": "...",    "title": "为什么 MongoDB 使用 B 树",    "author": "draven",    "comments": [        {            "_id": "...",            "content": "你这写的不行"        },        {            "_id": "...",            "content": "一楼说的对"        }    ]}
复制代码


使用上述方式对数据进行存储时就不会遇到 db.comments.find( { post_id: 1 } ) 这样的查询了,我们只需要将 post 取出来就会获得相关的全部评论,这种区别于传统关系型数据库的设计方式是需要所有使用 MongoDB 的开发者重新思考的,这也是很多人使用 MongoDB 后却发现性能不如 MySQL 的最大原因 —— 使用的姿势不对。


有些读者到这里可能会有疑问了,既然 MongoDB 认为查询单个数据记录远比遍历数据的查询更加常见,那为什么不使用哈希作为底层的数据结构呢?



如果我们使用哈希,那么对于所有单条记录查询的复杂度都会是 O(1),但是遍历数据的复杂度就是 O(n);如果使用 B+ 树,那么单条记录查询的复杂度是 O(log n),遍历数据的复杂度就是 O(log n) + X,这两种不同的数据结构一种提供了最好的单记录查询性能,一种提供了最好的遍历数据的性能,但是这都不能满足 MongoDB 面对的场景 —— 单记录查询非常常见,但是对于遍历数据也需要有相对较好的性能支持,哈希这种性能表现较为极端的数据结构往往只能在简单、极端的场景下使用。


本文转载自 Draveness 技术博客。


原文链接:https://draveness.me/whys-the-design-mongodb-b-tree


2019-12-26 17:282048

评论

发布
暂无评论
发现更多内容

中国人民大学周禹教授:数智人本主义-人力资源数智化驱动有质量增长

用友BIP

官宣定档!望繁信科技数聚·源力 2023 PRO_大会诚邀您参加!

ToB行业头条

Flink_state 的优化与 remote_state 的探索

Apache Flink

大数据 flink 实时计算

亚信科技AntDB数据库通过GB 18030-2022最高实现级别认证,荣膺首批通过该认证的产品之列

亚信AntDB数据库

数据库 AntDB AntDB数据库 企业号 8 月 PK 榜

合约跟单带单模式量化交易系统软件开发[源码搭建示例]

V\TG【ch3nguang】

量化交易系统开发 合约跟单 量化交易源码

数字孪生智慧粮仓Web3D可视化管理系统

2D3D前端可视化开发

智慧粮仓 智慧粮库 智慧粮仓管理系统 数字孪生粮仓 粮仓三维可视化

什么是云桌面?

青椒云云电脑

桌面云 云桌面

隐语小课|两方安全计算 ABY2.0 高效的 2PC 协议

隐语SecretFlow

大数据 AI 数据安全 隐私计算 开源社区

美团增量数仓建设新进展

Apache Flink

大数据 flink 实时计算

揭秘YouTube 的环境模式发光效果

汽车之家客户端前端团队

CSS youtube

zone.js由入门到放弃之一——通过一场游戏认识zone.js

OpenTiny社区

前端 js

支付宝小程序云效能:四大基于小程序生态的解决方案

TRaaS

阿里云故障洞察提效50%,全栈可观测建设有哪些技术要点?

TakinTalks稳定性社区

公有云、私有云和混合云的云桌面有什么区别?

青椒云云电脑

桌面云 云桌面

云桌面如何工作?

青椒云云电脑

桌面云 云桌面

如何从用户视角搭建可观测体系?阿里云ECS业务团队的设计思路

TakinTalks稳定性社区

R语言之基本包

timerring

R 语言

万字详解云计算中的云网络技术

华为云开发者联盟

云计算 后端 华为云 华为云开发者联盟 企业号 8 月 PK 榜

NFT铸造平台模式系统开发详情介绍[源码搭建]

V\TG【ch3nguang】

NFT 数字藏品开发

如何将IP定位SDK添加到您的 Android 应用程序

郑州埃文科技

软件 sdk

DEFI/LP质押流动性挖矿奖励发放模式系统开发

V\TG【ch3nguang】

DeFi流动性挖矿

Termius Beta for Mac(跨平台SSH客户端) 7.34.1中英文版

mac

ssh客户端 苹果mac Windows软件 Termius

如何维护大型 Next.js 应用程序

汽车之家客户端前端团队

next

企业网络安全守护神-行云管家堡垒机!

行云管家

运维 网络安全 数字化 堡垒机

开发者必看:深度解读隐语密态计算设备 SPU

隐语SecretFlow

大数据 AI 隐私计算 开源社区 密态计算

阿里云 X 森马 AIGC T恤设计大赛开启! 穿什么由你定,赢Airpods,作品定制联名T恤

Serverless Devs

阿里云 Serverless 云原生

Blender中有哪些有趣的插件

Finovy Cloud

blender Blender制作 Blender制作教程 Blender Apps blender软件资讯

合约交易所系统软件开发详情(源码搭建示例)

V\TG【ch3nguang】

交易所开发 交易所搭建

让大数据平台数据安全可见-行云管家

行云管家

大数据 数字化 数据安全 大数据平台

用友发布《大型企业项目数智化转型白皮书》

用友BIP

云桌面五大优势,开启智慧校园云端新时代!

青椒云云电脑

桌面云 云桌面

为什么 MongoDB 使用 B 树(二)_语言 & 开发_Draveness_InfoQ精选文章