专栏名称: AustinDatabases
PostgreSQL ACE ,PolarDB 3年, OceanBase 极速学习ING, MongoDB 8年经验, MySQL OCP, SQL SERVER, MCITP,REDIS ,做一个合格的数据库架构师
相关文章推荐
杭州日报  ·  反转了!确认系摆拍! ·  2 天前  
果壳  ·  为什么富婆都爱穿套装? ·  2 天前  
51好读  ›  专栏  ›  AustinDatabases

MongoDB 大俗大雅,高端的知识讲“通俗” -- 2 嵌套和引用

AustinDatabases  · 公众号  ·  · 2025-01-14 06:00

正文

开头还是介绍一下群,如果感兴趣PolarDB ,MongoDB ,MySQL ,PostgreSQL ,Redis, OceanBase, Sql Server等有问题,有需求都可以加群群内有各大数据库行业大咖,可以解决你的问题。加群请联系 liuaustin3 ,(共2700人左右 1 + 2 + 3 + 4 +5 + 6 + 7 + 8 +9 )(1 2 3 4 5 6群均已爆满,新人进7群400+,8群,9群)

这是MongoDB 宣传周的第二集,本集将讨论

2  在模式之间迁移如何更简单,让应用停机的时间更少

3  更好的支持板结构化的数据结构

说到这两个问题,我们首先要引入两个知识点,嵌入文档和引用文档两个概念。

1 什么叫嵌入文档

如果从字面的意思理解,是一个文档中嵌套了或包含了另一个文档,这是一种关联数据的方式,利用这样的方式我们就直接避免了JOIN,对传统数据库的表的JOIN。 这也是MongoDB 化解性能问题的第一个方案,因为JOIN的操作在传统数据库就是一个消耗性能的操作。

任何一个搞传统数据库的人都明白访问一个表,要比同时访问两个表要快的道理,这个道理正是MongoDB 化解传统 数据库性能不友好的第一方案。

{
  "_id": ObjectId("..."),
"name""Austin",
"address": {
    "street""XX路XX号",
    "city""天津",
    "zipcode""100000"
  },
"contacts": [
    { "type""phone""number""138xxxxxxxx" },
    { "type""email""address""Liuhuayang@example.com" }
  ]
}

正如上面的这个例子,一个是人的个人信息,一个是他的地址信息, 但我们设想一个人现在如果他有俩手机怎么办,他有3个邮箱怎么办,如果他还有真假名怎么办。

传统数据库怎么办,在弄一个表,在弄一个列来记录这些信息??

而在MongoDB中很容易解决这些问题。

{
  "_id": ObjectId("..."),
"name""Austin",
"address": {
    "street""XX路XX号",
    "city""天津",
    "zipcode""100000"
  },
"contacts1": [
    { "type""phone""number""138xxxxxxxx" },
    { "type""email""address""Liuhuayang@example.com" }
  ],
"contacts2": [
    { "type""phone""number""139xxxxxxxx" },
    { "type""email""address""Liuaustin@example.com" }
  ]
}

你看这就变得简单多了,实际上在讲MongoDB的时候,PG这个数据也有类似的设计,比如PG数据库中的Hstore。这些都是要化解一些传统数据库解决不好,笨拙的地方。

那么这里我们稍微总结一下,嵌套的使用场景是什么

在一个一对少的场景下,使用场景解决 1  减少获取数据的次数,由多次,改为一次获取。

2  与核心信息有关的信息,可以不用分类的存储在核心信息周围

3  简化数据的建模,不进行范式化的建设

4  数据高频进行访问的场景

5  数据量本身不宜过大(单条document)

缺点也显而易见

1  数据可能存在冗余

2  更新数据会更加的复杂

3  使用的场景有局限性,如一对多就不合适了,或者多对多的关系场景。

在出现缺点的时候,我们就应该使用第二种方案, 引用。嵌套和引用是MongoDB给我们解决大部分问题的方案。引用主要使用在必须要进行关联,但两个部分实在合不成一个"集合”的状态下。

比如:一个汽车生产商,它的配件信息和车辆信息的对接。一辆车上万个零件,而一个零件可以用在几种车上,这样的情况下,显然不适合用嵌套了。

那么我们怎么办, 1建立一汽车零件表 2每种汽车有一个零件的数组,或者将各个部分的零件门类分类,然后将零件表里面的零件编号以数组的方式存储在另一个表里面。

下面就是一个例子第一个是零件表,第二个是车辆表

{
  "_id": ObjectId("..."), // 零件ID
"part_number""P123456", // 零件编号(唯一)
"name""发动机", // 零件名称
"description""高性能发动机", // 零件描述
"manufacturer""ABC公司", // 制造商
"price": 10000, // 价格
"compatible_vehicles": [ // 兼容的车辆ID数组(使用引用)
    ObjectId("..."),
    ObjectId("...")
  ],
  // 其他零件相关属性
}
{
  "_id": ObjectId("..."), // 车辆ID
"vin""VIN1234567890", // 车辆识别码(唯一)
"model""Model X", // 车型
"year": 2023, // 生产年份
"parts": [ // 车辆包含的零件ID数组(使用引用)
    ObjectId("..."),
    ObjectId("..."),
    ObjectId("...")
    // ... 大量零件ID
  ],
    "parts_categories": { //按零件类别存储零件ID,更方便查询
        "engine": [ObjectId("..."), ObjectId("...")],
        "transmission": [ObjectId("..."), ObjectId("...")],
        "body": [ObjectId("..."), ObjectId("...")],
        // ...其他类别
    },
  // 其他车辆相关属性
}

这里查询起来很简单,如果要查询一辆车的零件,那么值需要分两步走, 第一步:获取第一个表的信息,以及各个零件的ObjectID

第二步:获取第二个表的所有OBJECT_ID对应行的需要提取的信息。

实际上这和阿里的一些MySQL设计的军规如出一辙,强制数据查询解耦。

这样的好处非常明显,如果这两个表都在UPDATE的情况下,产生锁和block的可能性很低,虽然在MongoDB中会产生锁,但在这样的设计下,查询对更新的锁干扰将微乎其微。

同时我们还可以注意到,如果一辆车的零件增加和减少,都只和第一张表有关,如果零件作废了,需要标记,只和第二张表有关。

同时我们还可以注意到,引用可以双向引用,比如我通过零件也可以查到,这个零件用到那些车上,零件也可以自己来一个车辆的数组。

通过有效的索引设计,查询信息将非常快。

写到这里一定有人问,这么好,有什么缺点吗?

聚合,无条件的聚合,无条件聚合且集合的数据量非常大......

返回到这期的主题

2  在模式之间迁移如何更简单,让应用停机的时间更少

3  更好的支持板结构化的数据结构

举例上面的例子中,如果是二位表格,一定会涉及到加减字段,对字段进行格式化的处理,应用需要注意相关的DDL操作,尤其大表,而这一切再MongoDB中根本不存在,因为无结构化的数据,你可以随心,在结构化的数据中,添加一些非结构化的特性,这才是MongoDB的精髓和超出传统数据库设计难题中的过墙梯。

那么MongoDB是花卷(嵌套),还是引用方式(面条),反正都好吃,加点肉馅就是肉龙和意面。

MongoDB 相关文章

MongoDB  大俗大雅,高端的知识讲“低俗” -- 1 什么叫多模

MongoDB 合作考试报销活动 贴附属,MongoDB基础知识速通

MongoDB 年底活动,免费考试名额 7个公众号获得

MongoDB 使用网上妙招,直接DOWN机---清理表碎片导致的灾祸 (送书活动结束)

数据库 《三体》“二向箔”  思维限制 !8个公众号联合抽奖送书 建立数据库设计新思维

MongoDB  是外星人,水瓶座,怎么和不按套路出牌的他沟通?

17000多张MongoDB表的锅 自动分析删除表数据难题--从头到尾的处理过程(文尾有MongoDB开发规范)
MongoDB 插入更新数据慢,开发问哪的问题?附带解决方案和脚本
MongoDB 不是软柿子,想替换就替换
MongoDB  挑战传统数据库聚合查询,干不死他们的 MongoDB 2023纽约 MongoDB 大会 -- 我们怎么做的新一代引擎 SBE Mongodb 7.0双擎力量(译)
MongoDB 2023年度纽约 MongoDB 年度大会话题 -- MongoDB 数据模式与建模
MongoDB  双机热备那篇文章是  “毒”
MongoDB   会丢数据吗?在次补刀MongoDB  双机热备
MONGODB  ---- Austindatabases  历年文章合集

PolarDB 相关文章


PolarDB 答题拿-- 飞刀总的书、同款卫衣、T恤,来自杭州的Package (活动结束了)

PolarDB for MySQL 三大核心之一POLARFS 今天扒开它--- 嘛是火星人

PolarDB-MySQL 并行技巧与内幕--(怎么薅羊毛)

PolarDB 并行黑科技--从百套MySQL撤下说起 (感谢8018个粉丝的支持)

PolarDB 杀疯了,Everywhere Everytime Everydatabase on Serverless

POLARDB  从一个使用者的角度来说说,POALRDB 怎么打败 MYSQL RDS

PolarDB 最近遇到加字段加不上的问题 与 使用PolarDB 三年感受与恳谈

PolarDB 从节点Down机后,引起的主从节点强一致的争论

PolarDB serverless 真敢搞,你出圈了你知道吗!!!!

PolarDB VS PostgreSQL  "云上"性能与成本评测 -- PolarDB 比PostgreSQL 好?

临时工访谈:PolarDB  Serverless  发现“大”问题了  之 灭妖记 续集

临时工访谈:庙小妖风大-PolarDB 组团镇妖 之 他们是第一

PolarDB for PostgreSQL  有意思吗?有意思呀
PolarDB  Serverless POC测试中有没有坑与发现的疑问
临时工说:从人性的角度来分析为什么公司内MySQL 成为少数派,PolarDB 占领高处
POLARDB  到底打倒了谁  PPT 分享 (文字版)

POLARDB  -- Ausitndatabases 历年的文章集合







请到「今天看啥」查看全文