## Detailed walkthrough
### [00:00](https://www.youtube.com/watch?v=a9B9lwqTr8s&t=0s) Data Model 的核心抽象与设计哲学:Separation of Concerns
在讨论具体技术之前,首先需要明确 Data Model(数据模型)最底层的设计哲学——关注点分离(Separation of Concerns)。这部分内容对应《Designing Data-Intensive Applications》(DDIA)的第二章。书中回顾了许多早期历史上的数据模型,例如在 20 世纪 70 年代 SQL 关系模型出现之前风靡一时的层次模型(Hierarchical Data Model)和网状模型(Network Data Model)。尽管这些老旧模型早已过时,但回顾历史有助于理解数据模型本质上是一种高度精炼的抽象(Abstraction)。
这种关注点分离的思想在软件工程界影响深远,最著名的范例莫过于亚马逊创始人杰夫·贝佐斯(Jeff Bezos)在 2002 年发布的“API 圣旨”(Amazon API Mandate)。贝佐斯展现出了极具前瞻性的战略眼光,明确规定以后所有跨团队(Cross-team)的业务协作与数据交互必须全部通过定义清晰的 API 进行通信,这一极具远见的决定奠定了后来微服务与云计算的基础。
```mermaid
flowchart TD
accTitle: Multi-level Data Models
accDescr: 展现从对外抽象到物理存储的四层数据模型体系
subgraph Business["业务与概念层"]
Ext["External Data Model<br/>企业对外/跨系统暴露的模型"]
Conc["Conceptual Data Model<br/>业务实体抽象 (如 Uber 乘客/司机)"]
end
subgraph System["系统与实现层"]
Log["Logical Data Model<br/>ERD 实体关系设计与表结构"]
Phys["Physical Data Model<br/>物理存储拆分与落盘机制"]
end
Ext --> Conc
Conc --> Log
Log --> Phys
```
在日常系统架构与设计中,数据模型通常可以划分为四个递进的层次:
- **External Data Model(外部数据模型)**:关注跨系统、跨企业边界时对外部所暴露的数据视图。
- **Conceptual Data Model(概念数据模型)**:偏向高层业务抽象。例如在 Uber 的业务中,核心概念实体包括乘客(Rider)、司机伙伴(Driver Partner)以及外卖配送(Delivery);而在 Facebook 中,则是用户(User)与地点(Place)等核心概念。
- **Logical Data Model(逻辑数据模型)**:系统设计中最常使用的形态,通常体现为实体关系图(ERD),明确定义系统中的数据实体以及实体之间具体的一对一、一对多或多对多关系。
- **Physical Data Model(物理数据模型)**:关注底层存储落地,即如何把逻辑模型拆解并具体映射到特定数据库的物理文件、分片与存储引擎中。
[33:00](https://www.youtube.com/watch?v=a9B9lwqTr8s&t=1980s) 声明式语言 vs 命令式语言:关注点分离的威力
接下来,Scott 对比了数据模型背后的两套编程范式——命令式语言(Imperative Language)与声明式语言(Declarative Language):
- **命令式语言**:代表有 C++、Java、Go 以及底层的 JavaScript 操作。特点是详尽阐述“每一步该如何做”(How to do),紧密绑定执行过程。
- **声明式语言**:代表为 SQL。其底层根基是关系代数(Relational Algebra),特点是仅向引擎清晰陈述“需要得到什么数据”(What to find),例如简单的 `SELECT * FROM user WHERE city = 'San Francisco'`。
Scott 强调,声明式语言的核心魅力在于**关注点分离(Separation of Concerns)**,他甚至直言:“如果将各种系统设计理念进行排名,关注点分离在我心目中绝对能排进前两名(Top 2)。”在声明式架构中,作为业务方的 Application Developer 只需关心业务需求本身,完全与底层的实现细节解耦。
处理层级隶属时,Prolog 会定义两条核心规则:
1. **基础终止条件(Base Case)**:如果 X 直接位于 Y 内部(`in(X, Y)`),则判定 X 属于 Y。
2. **递归推导规则(Recursive Rule)**:如果 X 位于某个中间位置 Z 内部,且 Z 递归位于 Y 内部,则推导得出 X 位于 Y 内部。
[33:00] Scott Shi: 如果将各种系统设计理念进行排名,关注点分离在我心目中绝对能排进前两名(Top 2)。
[25:00] Scott Shi: 不知道是不是 Mongo 有人起诉它
[51:15] Scott Shi: 没有一个好的 solution 是 one size fits all
[51:15] Scott Shi: 你把 Customer 2.0 想得太好了
[51:15] Scott Shi: 你不管是用旧的架构还是 Customer 2.0,从 database 的角度来讲都没有变过,你始终还是读的同一个 database,读的同一个 table。只是读完以后在 mapper 那层把原本割裂的 Rider、Driver、Partner 关系抽象映射成了统一的 User 逻辑模型。
[25:00] Scott Shi: 不太推荐 Mongo
[25:00] 听众: 还剩 70% 的 space 就不 work 了
[56:10] Scott Shi: fail miserably
Original transcript
[0:00] 我就说这个下周可能周三讨论然后再下周就变成周二周四讨论了也是时间改一下就这样的话周末的话时间更好安排一点好然后我们接着上次那个Data Model讨论Data model的话,一个很重要的设计里面就是separated concerns嗯这个呢是DDI Design Data Intensive Application的第二张,这张写的也相对是比较不错的,它列举了很多非常老的一些历史上的一些Data Model,比如说,就是在70年代Sycle出现之前的Hariaki Data Model和Network Data Model就是非常过时的,但是它除了这部分以外,还有一部分写的非常不错的。总体来说,Data Model其实是一个非常好的Abstraction,它采用的总体设计市场就是separate concern比如说Database就是一个对于Application Programmer,就是separate concern,Database就是guarantee durability,Guarantee Concurrent Control 这些,它相当于提供一个Guarantee,也是一个Abstraction那你在database上写的话就很多比如说同时有两个request进来,database会发生什么,database其实就帮你提供了一个这个的guarantee。然后separate concern其实用在很多方面,比如说这个Amazon对于API的mandate,就是Jeff Barrows,我也觉得Jeff Barrows是非常有visionary的一个leader。他就在02年的时候就说以后所有的cross team之间的coordination都要通过API,你必须定义好API来相互交流,这个也是非常有vision的,在02年的时候就做到这一点,就是非常有vision。然后data model其实是有多种data model的,比如说external data model,conceptual data model,external data model,就比如说你不同的company之间,或者是你对外的这个,这个你是exposed什么样的一个model的然后conceptual的话就比如说Uber的话就相对conceptual就比较简单,你有rider,有driver,partner,delivery,你另一个的话就是我想举个其他例子,比如说linkin或者是facebook的话就可能conceptual就是facebook,conceptual就是你有Facebook的话有Facebook user,有place这种是比较conceptual的。Logical data model相对来说是你design用的比较多的,就是ERD里面常用的那种,你把一个东西列出来,然后它之间的relationship是怎么样子的。然后physical data model就是你存到不同的database里面,你要把它怎么样把logical break down出来,然后存成physical的这种。然后我们又简单讲了SQL和NoSQL的这个简单历史啊,那Sycle呢是Sycle呢是relational database,然后它实际上是当时出来的时候非常revolucent的因为它其实提供了几种很重要的思想,最常见的思想就是separate concerns,就是database的developers focus on怎么样做concursion control怎么样做login,怎么样guarantee durability,怎么样guarantee atomic,或者是怎么样能revoque,就是那个rollback,rollback或者bot这个transaction他会在这张财产中的财产。然后这个其次呢那个Application Developer呢是想怎么样做index啊,怎么样把它index过去是吧,这个怎么样设计这个table schema然后其次的话还有analytic,那会儿analytic和application分的不是那么多,analytic developer的话就说我怎么样写这个SQL query,这个SQL叫simple query language,我怎么样SQL query来写然后能从这个data中得到更多的insights,这个其实分得非常开的,这个思想就是分的separate concern,把设计成不同的用途。然后但是大家都比对SQL比较frustrated,主要的原因就是scalability,在没有很好的sharding出来之前,没有这个杀点的概念出来之前,它其实是有这个Skills的限制的,看到这个Skills,Skills是可以支持非常大的,几百HundredTB的这个Data的,但是它Limitation在Operating System的,Operating System,我记得那天查了一下可能Limitation就是两个TB左右,就是Operating System,它这个对于这个Skills database的DataSize,Limitation大概是两个TB左右,不会差太多,Uber内部的话是500Gb,就是你如果是这个,你在一个,一个,一个,如果有超过500Gbps的话,你可能就要考虑用其他database,而不用就简单的卖 Seql 了然后所以scalability如果没有sharding的话是很成问题的,其次的话大家prefer用一些free and open source software,只有2B的可能偏向于用commercial database,因为commercial database有很多不透明,并且software其实中间有很多非常ugly的地方,比如说景强经常谈那个redshift里,它的code其实很多都是九几年写的,97年98年写的,他们还用那个C++98,C++99,反正就是
[5:00] 里面连很多基础的一些library都没有的,他们还得自己写一些自己customize library,因为他们根本没有机会去更新C++的那个Version所以1114什么都不用想,19都不用想,还是用98还是99的Version中间还是非常旧的这个,所以虽然看起来Redshift是比Hive要快很多,Redshift的performance比Hive要快很多的很多时候你在Hive上跑一个Core要跑一天,在Redshift上可能就十几分钟就返回了,他们从performance的角度来讲是真的是优化了很多所以然后去优化的,所以你update一下,upgrade一下language,可能会出现很多broken的地方。其次的话,包括Uber的Airflow,Uber的copy,就是Piper的Airflow也出现过这样的问题。他们是在Redshift里面他们copy了一个就是Postgres的一个PostgreSQL Core Engine 就是它怎么样把 SQL CorePost 成 Execution Plan,他们叫Front-end,就是把Sycocory,Post 成 Execution Plan,它是Copy的一个非常旧的Postgres的一个,按这个,是十几年前的版本,导致它没法更新,它就必须在那个Version上不停的更新,自己更新。Uber有类似的,Uber的Piper是Poppy的一个非常old version的一个Airflow,然后你后面的话发展就不一样了,就得自己更新。虽然用起来可能可能你可能进行这样的优化那样的优化,但是总体来说你和这个open source的ware就脱节了嘛,commercial software就有这样的问题然后其次的话,relational schema的话,它相当来说它非常restrictive,很多时候就非常frustration这个之前的话,比如说在SQL,我记得SQL 5.7之前,但是不是很好支持 Jason 的,所以你这个 field 只有几种模式 就是什么 text 啊 或者是 integer 啊这种 所以你不能存一个 JSON 上去可能在5.7在之前嘛,就是不是很好支持这个schema的,如果你要存一个就是relatively flexible schema的话,你需要maintain自己的schema,其实中间会增加很多complexity。所以这个NoSQL的话,它基本上都是非常dynamic和非常expressive data model。然后最后SQL是最painful的一个point,也是基本上所有人都讨厌的一个point,是有一个非常awkward translation layer,叫ORM。Object Relationship Matching,这个的话其实有很多Complexities在这个里面的,它很多时候是Boiler Plate Code,你有时候看的时候你都觉得它是自己Automatically Generated如果你有看过那个4M code,很多时候都觉得automatically generated,但是实际上里面有时候写的不好的话会有很多customized logicbusiness logic,然后很多时候broker的时候就那块broker,就是你其实ORM这块这个codebroker了,但是平常时候都会略过这一块。然后已有的几个,并且已有的几个ORM的library并不很好,因为我们到时候在讲这个SQL transaction的时候会看到它为什么已有的ORM很多时候实现的不好。在印度上你有一个非常 painful的RM layer我们这块上一次讲了就是怎么样用sql存,怎么样用document存,对于linkin来说,sql的话就把它breakdown成不同的table,如果是document存的话就存成一个jsonfile就可以了,如果用mongodb的话就是jsonformat就可以了那Normalization的时候呢,假设我们把它做Normalization有什么好处呢?首先你就是你可以consistent 是吧 你这个spelling 或者是style 比如说这两天要把white list 变成什么blacklist变成blocklist 是吧,你这样的话只要一个地方改了,其他就要全变成blocklist了Whitelist好像变成Permitted List什么的,就是这个要改变是吧,这个你如果是成为Free Text的话,你需要改无数多个地方。然后其次的话是可以Avoid Ambiguities,比如说你有Several City,有Same Name,Similar Name,Spinning Mistake什么的。如果是存存这个Normalize以后,你可以说这个City ID是多少,然后你City命名的时候你可以跟着改了然后update的话相对来说也是比较容易的这前三条基本是比较相似的一致的其次的话是有一些localization support,因为有的这个data呢,比如说,比如说San Francisco,我们比如说西雅图吧,西雅图不是建了一个西雅图联邦,最近叫了一个Chess联邦,你假设它真的列出来了,那这个西雅图自制联邦,然后会在西雅图市里面,然后西雅图是在华盛顿州里面,华盛顿在美国,那你在search,
[10:00] 在华盛顿州的公司的时候,西雅图自治联邦也会把它列进去,因为有一个localization,就是localization search,这个是一些relationship,是可以better management的。然后其次的话,你把它翻译成不同language,我知道就是大家还有人用比如说linked中文版的时候,它可以translate的时候更formal一些,这样的话也比较好理解。其次的话这个这个relational database 如果把它normalize的话有一点好的是many to many relationship 比如说这个是我的一个link in profile 是吧 我可能在Southforce工作做 然后Southforce突然换logo了这个比如说是另一位Southforce员工 廖文文的profile 是吧 然后也在Southforce工作 结果Southforce换名称了或换logo了那他只要在同一个地方换就行了 因为这个都是pointer这个是many to many relationship,相对来说manager比较好一点。但如果你是document的话,你这块除了其实这个string,你可能需要对于所有的Salesforce的这个都需要update,需要Salesforce name什么都需要update。然后这个Seql的这个我可能以后会花点时间讲的比较多一点这个Seql其实是一个非常非常复杂的一个东西Seql虽然看起来是很简单但是就是现在是老生常谈就感觉什么事都用Seql但是Seql本身是一个非常复杂的东西它中间有很多中间有很多优化的部分比如说,比如说,SQL里面有很多优化的部分,比如说当你叫一个SQL Core的时候,它首先,SQL有一个就是有个interface,然后他会把它这个就是interface这个命名有时候不一样但一般来说这个叫什么sql-pulsor或command-pulsor的命名有时候有地方不一样但是他会把这个command的SQL先pause一下就是写过Compiler的话,这个Pause就和那个类似的就是,它会首先verify你这个是不是valid SQL Query,然后Pause一下,然后把它变成一个QueryTree,Compiler的话是Ebstract Syntax Tree然后他这时候会做optimization,Sycle optimization是非常非常complex的一个地方,Sycle optimization叫Beastmo,就是你其实是他其实花了几十年的research,很多PhD model进行research,然后把它optimize一个非常高效的地方,像景祥那个不是在他说那个Redshift,他实际上他optimization为了现在为了提升他那个效率,已经开始用那个嗯就是那个program bar,array 来进行实现了,pgma 还是什么,我忘了那个什么了,我之前也写过。PGFA写了,它其实已经不是用传统的计算器,Generic Node来去optimize,它用PGFA来optimize,你可以写一个CPU,用PGFA写一个CPU,它效率更高一点,它比Generic CPU效率更高一点,就是他们已经用了这么擅长的人了,另一个用PGFA的另用PGFA的这个optimized的是那个Hedge FundHedge Fund 赃了好多PGFA的人,就是他是为了把那个lentency因为它这个Hedge Fund里面一毫秒的Lentency值好几个Million所以它就是为了用PGFA算的速度是比传统的CPU快的就是把它先提前program好了算的速度是比CPU快的它就开始写这个优化了所以这个optimization是优化呢其实是SQL这个optimization的优化其实是它最复杂的地方就是它所有的research花了很多的地方然后它会生成一个Execution Plan但是你所有的NoSQL这个optimization基本上都不做的,因为它不做这个optimization,你知道吗?就很多时候它是没有这个SQL optimization这一步的。所以很多时候就没有这个optimization这一步,所以 depend on this noSQL,因为 noSQL本身自己差距很大好,然后optimizer做完了以后会产生一个query plan然后 query plan 就会交给这个 storage engine了Storage engine 里面呢 它其实是一个 file system 它有 transaction manager 就表示这个同时 manage 多少个 transaction 有一个 buffer manager 这个 buffer manager 就是表示是这个file底层,比如说哪些pages是Dirty换过来,哪一些是在BufferPool里面,它会根据你Modify的东西,然后把它同时写进去。然后除了这个以外,就是SQL和Filesystem有不同一点的,除了这个SQL Optimizer以外,Core Execution Plan以外。还有一个不同点是SQL会加Log,会ManagerTransaction,就是你所有写东西都会在Log里面有,会有一些Transaction的东西。帮你manage更好的transaction,这个不懂无所谓,这个你要看的话,它能整整讲好几百小时的课,这个不懂无所谓,就是现在有概念,就是SQL其实是一个非常complex的东西。
[15:00] 它下面这块是这个Storage Engine 是Engineering非常high位的这块有很多优化Engineering的海门,你可以到时候如果有空的话,我们可以看一下它怎么样design,怎么样manage这个buffer,怎么样manage这个transaction,怎么样manage这个叫riderheadlog,其实有很多复杂的地方。但是它真正的这个research复杂的地方,其实这个SQL Optimizer这块,这个其实是花了很多PhD在上面优化的。那么如果我们对比relational database和document data model的话它其实single record performance是没有fundamental difference,就不会差一个数量级的但是,我们说这个Document Database,比如说,我们讲这两个区别如果你是读一个这个配置这两个performance有什么区别呢?这个performance区别就是这个只要读一个record就行了,这个Mongo,就是这个Document Database,只要读一个record就行了。但是如果你用Sycle的话,你只是读了一个,两个,三个,四个,五个,六个,就是读了六个table里面的若干record。这就是它的区别,就是它把这个七八个读变成了一个读,在这个Document Database 里面,这就是它这个优化的地方。但是它这个单个Record的Performance是没有区别,因为SQL优化过很多很多次。所以这个SQL的performance其实是非常不错的,它那个不管是join什么,其实从SQL来说的performance是非常不错的。所以你如果看Money to One, Money to Mining relationship 的话其实本质上两个没有区别,甚至这个Document Database效果要更差一点,特别是many to many,因为Document Database SQL是读Foreign Key,它其实那个manyMapping,它那个4k的那个Join是在in-memory做的,它效率很高,但是你在Document database里面,你实际上Document Reference,你是这样要多一个Round Trip,你是要去,我先读这个table,是吧,我先读这个Document,我读了这个Document里面有个Document Reference,我再去把那个Reference的Data再读出来。如果你用Document,就是如果用MongoDB的Client的话,它可以把这两个变成一个,就是它可以做一些优化,在Client的端进行优化,变成一次读,但是它还是总体来说,它Performance还是,就是它这个Reference的Performance,Document Reference Performance,还是比Joy要稍微差一点。但是Document Data Model是比较schema flexible 的。它就是从某种意义上来说,它的 performance 呢,因为它所有的 data record 在一起,它那个 local 。locality,locality,locality,locality,就是它data record全放在一起,所以你逐一个record的时候你实际上data全组在一起就组一个地方而不是读多个地方,像我们之前看的那个linkin的case,如果你读sicle的话,你实际上读从七个table里面读七八个records,你实际上这个records读起来是非常分散的,但是如果用document database,你只要读一个地方就可以了。并且这个SQL相对来说呢更support是join,比如说你这个many to many,这个可以join, normalize一下,many to many support非常好。其次有一点非常不一样的地方,这个也是作者自己命名的,这个书里面做自己命名,我觉得说的蛮有道理,就是Sycle和MongoDB,Sycle和DocumentDB,这个schema其实都是有的,但是它Infos的时间不一样。在 SQL 里面是你叫 Schema on Write 意思就是当你写进这个 database 的时候,你其实就对了 schema 进行了要求比如说你这样写的时候,他会对已有的这个schema验证一下,你是不是这个record type对不对?然后你这个这个Record Type 对不对 然后其次的话会看你这个record会不会满足这个要求,它实际上在write的时候进行了schema的验证但是你如果不符合他的schema,这个write会被reject但是这个Mongo其实是schema on read,就是你写的时候你不管它什么都可以写,你只要是个json就可以写,但是你在读的时候你expect他有个film,有个column,比如说我们之前讲那个crawler,这个叫smartcrawler,能detect automatic change,是吧?比如说你要crawl这个news website,你还是expect他有一个news title啊,或者news author,expect他有这个有这个column的,所以你可能读的时候,就是你写的时候就写个json,但你读的时候你express它有个title这个column,如果没有这个column的话,你可能会需要处理它的exception 的情况。所以这个就是sicle or no-sicle的一个显著区别就是你到底是这个schema你是在写的时候infos还是你在读的时候infos谢谢大家然后这是那一点就是这个schema读的时候还写的时候Inforce不同的用处就是你它这块给了一个use case,比如说你之前的user name是一个name,但是你想把这个table分成两个就是新建一个正在user name,exact first name,是吧,你这些是吧,
[20:00] 安全的时候是,就是first name, 空格, last name, 现在你希望 extract first name那如果是这个SQL的话,你实际上就需要update你的SQL schema了你需要的什么呢,就是你需要update user,把这个first name 呢,就是从那个name里面读取出来然后变成一个单独的column,这是非常static type,或者是schema on write的这种就是单独提取出来一个这个,但是这块我想提一下MySQL其实现在非常灵活了MySQL你可以定义一个Virtual Column就是什么叫Virtual Column这个Column其实是理论上在底下是不存在的但是你读的时候可以进行这个Column可以对另一个Column进行一系列运算然后计算出来所以这个你可以没有一个Column叫First Name但是你First Name可以变成一个Virtual Column它有个词我忘了具体叫什么了就是Virtual Column就是你可以对这个Full Name进行运算然后运算,然后把这个first name提起出来然后你读SQL的时候,就是select的时候,你可以直接select first name这个MySQL就是5.7版本之后是支持的所以这个也不一定要,也不一定需要做这个,就是真的把它update一个first name然后另一点来说,当你进行这个操作的时候Postgres效率是比较高,当你进行update column或altered column的时候Postgres效率比较高的,它实际上就是在原有的table上加一个column但MySQL是当你进行altered table的时候,它其实会把整个tablecopy一下所以如果你有一个非常大的user table,比如说几个billion row的话MySQL是非常非常满的,可能会take hours and days去copy这个table,所以在outretable,在MySQL里面要做起来非常小心但是一般的其他的database是不会有这个问题的我就这块说两点,一个就是如果是这种简单的运算,你其实可以不需要加一个真正的column你可以加一个你search一下MySQL的文档,它其实可以加一个virtual column这个column其实在database程度是不存在的,但是你从MySQL读的时候,你可以select first name,就是背上另一个column进行运算提取出来但是如果在mongo里面mongo里面的话,其实就相对来说不需要了你不需要对data进行任何运算你在写的时候,你在读的时候,你在读这个first name的时候你可以说它有没有first name,如果没有first name的话把first name从这个name里面提起出来,然后再写到database里面再写到database里面这个其实是有一个cavet,是有个陷阱的covet的陷阱是什么呢你在读的时候其实进行了database写的操作就是你在读一个database进行database写的操作这总体来说一般来说不是一个不是一个好的一个design就是你get一个table,get一个数据结果对于database写的操作一般来说不是一个好的但是mongo在这块已经就是在mongo里面变成一个约定书层的东西好,我们这块有两个问题啊然后说,一个是Links问的说写的时候如果json document写的时候如果document-based或者json,json里面没有的field有没有的field可以吗?我不问这个问题啊Links能说一下吗?就是这样的,就是那个,能听到吗?我能听到比如说我现在已经有的一个Document然后它的JSON比如说就是Name然后还有一个Job然后还有一个就是比如说Adress然后我现在有一个新的一个写的Request过来了然后这个写的时候这个时候我的JSON里有一个新的Field它之前没有存在过比如说它现在叫FirstName它写入的话会被接受吗当然会接受你提到了InforceOnRate它是InforceOnRate就是它写的时候任何都可以接受但是它读的时候你要是没有FirstName的话你可能需要额外的处理任何Json都可以写这是Document Database就是他当时就是我写过一些Mongos我其实上学的时候被Mongos骗过写过很多Mongos但是你知道在业界写过Mongos的人基本上都讨厌Mongos但是他那个Signin上学的时候我上学的时候他那块Signin特别热也写得比较好被Mongos骗过好另一个question说每次读的时候都做这次提取还是最后还是这么读一次后整个table就Virtual Migrated Forever以后读的就快了你尽管这个问的问题宇全你问的问题应该是mongo吧不是我说是你刚才不是说那个traditional database它会再create一个什么virtual column吗对它那个virtual column是永远不materialize应该是不materialize就是你读的时候
[25:00] 你比如说你读你读假设你读的first name从这个SQL里面读 first name是它是怎么读取呢?它其实是读取fullname,然后进行运算,然后把firstname提取出来,然后给你的。就是它其实是没有这个,我的理解,它其实是没有first name,在database底层里面,其实这个file里面是没有first name,这个column,它是读取full name,读取出来,然后把 first name 提取出来然后给你的 返回你的 所以它跟这个传统呢 full name 这个存在 database 其实是不一样呢然后被芒果骗,Paul说被芒果骗过什么是不太推荐芒果吗?不太推荐芒果。我有很多很多例子,就是我用过,见过很多例子,在不同公司见过很多例子。Mongo的performance很糟糕我举个例子,我不提这个公司是哪个了,因为我其实理论上没在这个公司工作过。它用Mongo存这个context,这个context只有一个边点,然后这个mongo就crash掉了, performance就很糟糕了- 还剩70%的space就不work了 - 对,还剩70%的space就不work了- 还剩30%的space就不work了 - 对,就是capacity只用了70%,这个mongo就不scale了mongo的问题主要是scalability和index的问题你想mongo的话,它其实是你读一个object id,或者document reference读document的gsm它主要是index问题,它没有index,有一些requirements meet不了它有了index造成了更多的问题,并且scalability还是有问题嗯用过Mongo的特别就是你如果做side project或者smart project无所谓,但是这个用到production真的skill出去的时候其实有很多问题包括这个,你其实看这本书,我觉得这个书的观,这个作者的观点,其实有很多地方或是一致的,然后你如果看纸质版和电子版,它电子版还删了一部分,就关于Mongo,说了一道关于Mongo的画画还被删了,我不知道是不是Mongo有人起诉它,但是我看的是纸质版的书,纸质版上有额外的数据,挺有趣的,好,再解释一下每次读都进行了写的操作的Mongo database,Document database,比如说你这块,你这块你实际上是对于first name,优优独播剧场——YoYo Television Series Exclusive就是当你读这个first name的时候,当你改变这个schema,在monger上改变这个schema的时候,你读这个Document First Name的时候,这个Document First Name如果不存在,它没有立马对这个Schema进行改变。当你读这个Document First Timing它不存在的时候,它实际上是把那个Documentsplay出来一个first name然后再写进database所以你其实这个读进行了写的操作,就是有点像http.get实际上有一个database write的操作,这个其实是不是很好的design,不是很好的design,这个是一个小的red flag吧,但是mongol这已经把它做成一个convention了,就是已经这么做,大家都可以接受了。Advantage on schema unread 就是当你读的时候进行schema验证的时候有什么好处呢?就是你比如说你这个data不是相同的structure,比如说我们在crawling的时候每个data的structure都不一样,比如说这个game replay的structure就和news的structure不一样的话,那你肯定希望schema on read,就是你希望更flexible一点。其次的话,如果像这种structure data实际上是被external system比如说你这个比如说在crawler里面,你其实自己也没法对这个structure进行决定,你只能是External system进行决定,那您肯定是希望用这个,就是希望把它变成一个JSON,然后直接存一个JSON就可以了,那存成Document Database是可以的。然后其次的话,其次的话当你有很多不同type的object,比如说每个type是hintergenius,hintergenius是什么意思呢?我后面会有个例子,就是说每一个object type不一样,比如说这个type就是一个newsnews,然后那个type就是一个game replay的话,那你希望就是把它,然后其次,其次你又不能这个create一个什么game replay table,那个create一个news table,你希望把它放在一个object table里的话,那可能用这个schemaonread的就是比较好的approach。谢谢大家这种情况下的话,当你有schema的时候,比如说你是crawler的时候,当你有schema的时候,一旦crawler的website改变schema,整个system就broken了,那还是把它分开好一点,schema是一部分,crawler是一部分,poss是一部分,这样会好一点。其次的话是Data Locality这块,Data Locality这块也有很多很有趣的地方,这什么意思呢?就是当你看这个Data Base Access Pattern的时候,Database access pattern 当你常见的common access pattern data 是不是放在一起的
[30:00] data locality. Data and locality are what's good for? First of all, data you read performance will be higher, is it right? You put data in the performance will be higher. In addition, you have to be found when data is reduced to fragmented, is it right? For example, in Salesforce, I'll use Salesforce as an example. Salesforce is actually a very good example. Salesforce is called multi-tenant environment. What is the meaning? For example, Uber is Salesforce customer. Lift is Salesforce in customer. The record in the database, in the database, is in line by line. User table is the Uber record, the 16th is the Leaf record. This is a very possible way, because it is metadata. In Salesforce, I have a request for a new user, I have a new user. It will first customer logic, like Uber has an additional validation, and it will be done with the company ID. and the database底层 is in the user table in the user table. So Uber customer user. Leafs are the same. Leafs are the same. Leafs will go to verification. But when you write the database, line by line is the same. You can find this problem. You can see your competitor data together. If you're not going to be released, how will it be? This is the first thing. Salesforce has built a Cionala, it was used to use Oracle Database. Cionala is to use a different way to use. It is to use a layer database, appending log, to change B+Tree. It is to do the Oracle. It is to guarantee you Uber data. It is to put in a separate area. Cmog data is close to each other, is to put in one side. increase data locality performance. Google Spanner is similar to it, it is a relational data model but it can also allow you to specify table row, to have a relationship with each other. and put in a parent table. Cassandra is similar to the same. Cassandra is able to create a partition key. Partition key is to solve the data locality. So why do we say schemeless is not good? Schemeless is not going to solve the data locality. Schemeless is to solve the data locality. Schemeless is to solve the UID. You can read a transaction. If your record and UOID are not the same, it is in two shards. You can't do cross-shards. You need to read two things, this is a mess. You can't control your data locality. So in the new Docsdown, it's been taught by Cassandrum. You can specify a partition key. When you want to write a record, it will be in a short period. You can have Application developer can be used to control your business sense. So, Dota locality is a very important thing. And the other thing is the data model. There is a different point. imperative language and declarative language. This is the programming language. It is a different place. Impressive language, like C++, Java, Go, these are imperative language. For example, this example is a simple example. Ciao a l'easys! It's JavaScript, it's JavaScript. And the next one is SQL. SQL is a declarative language. It is a logic. It is a logic. It is like... Relational Algebra is the general expression of the real physics. And you can describe what you need to find. This is different from the different types. Let's see if I can see if I can see if I can see if I can see the different values. First, the difference is declarative language. You can just see what data is like. uh select start from user table, where user ID, where user city is equal to San Francisco, you can just say that. It actually is the system database in the core, optimize your requirement, and then it's the best way to go to the data. And then, you are a separate concern.
[35:00] 你把 implementation detail和这个你就是作为Application Developer的需求分开了那这样的话,比如说当它对database的这个 query optimizer 进行优化,甚至全部取代的时候全部换掉的时候,这也是API design的时候,就是常见的,就是你把这个implementation全部换掉了,那你其实对你来说也没有影响,你还可以用同样的一个SQL来使用,因为它这个agreement没有变,就是select user from San Francisco,这个agreement没有变,但是imperative不一样,imperative language是和implementation detail有关的,你比如说这个select的时候,如果你这个implementation换了的话,你其实会影响你的result的,很多时候会影响你的result的,然后其次的话, declarative language 很多时候是不garanty任何 order 的。实际上,这个,像 select SQL,这个 SQL,就是 simple query language,它是非常,它functionality是非常limited的但是它因为 functionality limited 实际上给这个这个platform developer 多了更多的空间去优化,是吧?这个是有更多空间的空间,其实还可以平行执行,parallel execution,因为你比如说你这个table,这个user table is sharded的,你shard的不是根据CTK来shard的,你select user from San Francisco,它有1000个shard的,你可以放在1000个shard同时执行,你的return效果很快的,但是imperative language的话,你可能就需要更多的一个一个shard的去读,你可能需要考虑更多的implementation detail,比如说这个data有没有在这个shard上,你就要考虑这个implementation,但是这个sicle,或者这个declarative language,你不需要考虑这个implementation,是非常好的一个separate concern,separate concern是设计中非常重要的一个理念,如果我把它放到这个设计,我自己理解的设计里面,我可能会把它放到top two,就是最重要的一个理念之一,就是separate concern,你怎么样把一个非常复杂的系统分成不同的层,然后每一层和每一层只相有一种agreement,然后就 separate concern最后一点是MapReducer呢,既不是Declarative Language,也不是一个Imperative Language是Somewhere in between好,这个就imparative和declative我就说完了,我这块再给举个例子吧,如果你之前没有接受过这个programming language课程的话,可能这块有点难理解。嗯我们就举一个常见的例子比如说我们在写HTML和CSS的时候,比如说你HTML可能会定义一个table,这个table叫Whatever table,user table然后你对这个table呢可以进行class进行定义对吧比如说这个class是说这个class是user的时候我把它染成绿色的这是 declarative language,然后你可以把这个比如说这个贴宝检上绿色的,然后你在这个CSS里面,可以说我现在不喜欢绿色,我改成染成红色的,那所有的这个user table在你改成红色的之后,css瞬间就把它全部渲染成红色的了。只要是class属于user table你的这个table就是红色的,就是在CSS里更改的时候。但如果你是imperative language,如果你用java script去展示的话,你可能需要一个follow loop去run这个,然后把一个一个table,改成红色的,那你比如说你在这个CSS里面,当然CSS本身就是属于declarity文的language的一部分了,你如果想展示的话,你需要这个javascript重新再run一点你需要去重新trigger这个JavaScory重新run一遍才能把所有的推包染成红色的这样的话其实你就是和implementation detail相关嘛这个例子其实在这本书上也挤了大家如果有兴趣的话可以再读一下有什么问题吗?有什么question?好,我们进会看这个Graph Theta Model很多人很喜欢Graph Data Model,但是如果你真正读到它的details的话,你可能对它喜欢不喜欢就打一个问号了。Graph Data Model里面它是有两种,一个是Vertix就是nodes,一个叫relationship,就是nodes的连接就是这个age,一个是点一个是线常见的Graph Database,Graph Data Model或者Graph Database能解决的问题,比如说出色Graph,比如说Facebook就是Social Graph,比如说Web Graph,你说的Web Page,其实每个Web Page就是一个Node,然后你的superlink hyperlink其实就是这个hs比如说这个road和network,realway network它那个age就表示roads,然后它那个intersection就是node常见的这个graph 比如说这个car navigation system 你要去找这个最短路径
[40:00] It. weighted. Graph Database, the Innovated Graph Database. And then, for example, Google PageRank You can use this web graph to do the popularity of the web page. Cool, I'm not saying that. Wow. This is a graph. How? This is from Facebook's paper. If you look at Facebook, Alice in Golden Gate Bridge and Bob in Golden Gate Bridge Cathy said, wish we were there as well, David likes this. This is a very complicated graph. It's a very complicated graph. What is the user? Alice. And the user is friend. Bob and Cassie are friends Cassie and David are friend, which is user node, which is a user node. And they are relationship, which is friend. And then there is another node called location, the Golden Gate Bridge. This is a Golden Gate Bridge name and location. Then there is a check-in action, the action is made by node. The action is who check-in? It's Alice's check-in action. And then tag-in Bob. So this check-in is where is check-in? This check-in is in Golden Gate Bridge check-in. 其次呢? The last thing is, the check-in is comments. This message is a check-in type message. Check-in is comments. Comments are texts. It's who is author and who is like. The whole situation is in the situation. This is a hint-genius graph. Facebook How to break down and become a social network. And then... And this is what I proposed to our team. I was in safety team. I proposed to our team. proposed the one. Paul said, "Facebook use graph data model to use Social Graph is using Graph Data Model, but the underlying is using Shared SQL. The tool is used by multi-leader shredded SQL. It is similar to our schema list. The tool is a scheme-less design, which is a scheme-less design. So it actually uses mycd code. It uses mycd code. This is the Uber safety code. done. We are not in this case, we are in a bit of trash. I won't say that. But actually Uber safety case can also use this. For example, you can use user Alice There are Bob and Cassie. And then Alice and Bob have a co-write, and shared write. and there was an inter-personal conflict, and there was a conflict. Then he filed a ticket, the Blitz Ticket is Blitz Contact Ticket, which is Uber's own ticket support system. When you're not satisfied, you're going to report it, it will be a please ticket. And then, if it's serious incident, it will be zero tickets. So Cassie is confirmed in zero tickets. And David will handle this incident. So it can also be a For example, in this case, there are four users, right? Alice, Bob, Cassie and David. David is Uber's employees. And Alice reports an incident. And she associates in this trip. Order and Job. She associates in this Uber ride. And Cassie is the driver. She is a service trip. She is with David. conversation, right? And this is an incident. The incident is with the order and drop, and the trip is connected. and then connect with the tickets. It can be designed to be like this. The data will be more similar to Facebook. You can do graph traversal, work on this graph. You can set up a visualized system. get the same information about Alice, you can read the profile, roles, activity, incidents, trips and orders. You can read Alice's information. For example, if you want to read the incident information, you can read the incident information from who has been involved, who has been involved, who has been involved, who has been involved, who has been involved, and who has been involved. And there are some associated trips, the trip is telemetry data.
[45:00] 就是这个GPS data就是你这个在每一分每一秒在哪一个地方,你的速度是多少,加速度是多少,然后这个加速度方向是什么叫Telemetry data,就是比如说你开车的时候就有很多Telemetry data,就是你每一分每一秒在GPS哪一个位置每一分每秒在GPNS哪一个位置速度是多少,加速度多少,加速度方向是多少,这个就是tiny metric data然后你还可以比如说你还可以对David的这个information有更多的信息,response time,ticket work on,就是他work on哪些tickets,说的conversation,rating你可以用非常generic的entity relationship 实践的safety 结果但是读懂原因没有时间,主要的原因是没有时间,没有时间是时间。这是我觉得我最近比较 push 想做的一件事情,但是没有时间是时间,因为有更多 urgent project好,Graph Database 呢,如果你只是说这种,其实你是没有任何 advantage,就是说你其实完全可以用 SQL 存。你完全可以用 SQL 出来,你只是读这种简单的这种,右面列出来所有例子我右面列出来的这个所有例子就是比如说不管你是读一个人做事件、做事件、做事件、做事件、做事件、做事件、其实你用sql存是完全没有performance difference的,完全没有performance difference的。但是有一种Case,这个Graph Database是有它的自己的优势的就比如说这个例子在这个例子里面,我们这块有一个非常复杂的,就是Nested Relationship,有一个continent,叫北美,是吧,美国在北美里面。然后爱德华在美国里面,然后Lucy是在爱德华出生的但是他生活在伦敦,然后他和Alan结婚了他和Ilan同时结婚了,生活在伦敦,伦敦是英国的,英国在这个英国,英国在这个UK里面,是吧?然后这个在Europe里面。然后这个Ilan是在这个另一个地方出生的,他属于France,是吧?这个City我不知道怎么读。Codida,这是在另一个地方,它属于France,是吧?这是一个graph database。如果你想这个Core的时候,就说,比如说,举个例子,你想说,我想找见一个married couple,是吧?在Europe生活,其中有一方来自于北美,另一方出生在 Europe那这样的话你用Sycle表达非常非常复杂但是你用Graph Database就非常非常容易我再重复一下这个问题,这个Corey可以思考一下,对于SQL写的比较多的,或者有点建议可以思考一下你想再写一个sql query说我想找一个married couple然后他们现在生活在Europe,但是其中一方出生在北美,另一方出生在Europe。这个 query 是用 SQL 写起来是非常复杂的,所以就用 Graph Database。常见的 Graph Database 也有两种实践,一种叫 Property Graph Model,一种叫 Triple Star。Triple Star实践方式,Triple Star有点像那个三段逻辑论,我这块没有提,只提了 Neo4j 这个,因为 Neo4j 算是 Graph Database 里面,现在商业化和 support 相对比较最好的一个地方。它是推荐一个叫 Index Free 的一个 Graph Database。如果我们用relational data model,就是说像之前提的那个Facebook Social Graph,用relational data model来实践它的话,要怎么实践?你首先要提一个Vertix,是吧?Vertix就是这个点,你可能有个Vertix ID,然后你有一些property 就是vertix然后你要写一个Edge,就是把这个点连起来的线是吧,然后你Edge有ID,然后你Edge的话连Vertex它的tail vertex是什么,然后head vertex是什么,然后你这个edges可能要label,是吧?你比如说这个label可能是boeing这个label,可能是living这个label,可能是marry这个label,是吧?不同label,然后你这个edges有一些property是吧?就是就比如说这个Boeing的话可能有些额外的Profit,然后这样的话你可能需要两个Index一个是index 是什么呢,index 是这个可能从一个vertix的,它那个就是箭头指向的起始方来search你也可以从一个箭头的中指方来search 是吧像这种情况下的话,就是这个箭头的这个tail index起来,然后箭头的head index起来这就是你可以这样来model这个graph,就是有node和edges,有vertix和edges,然后你index的时候把这个node index起来。那如果你要想,sorry,如果你要写,就是这个我们刚才说的这个逻辑的话就是说你看找这个人
[50:00] 其实它这个逻辑还更简单一点找生活在欧洲出生在北美的人然后找见它的property name但是你join的时候就很复杂了你首先得我们看一下这都是找见什么意思第一个cord的意思是说我们首先得找见北美这个node然后呢找见所有的location在美国的location对吧找见所有的在美国的location所以第一个就是找见所有美国的location第二个相似的是找见所有的Europe的location第三个是什么呢第三个是所有的找见在美国出生的人然后第四个呢是找见所有在Europe生活的人然后这个Jone一下然后把name读出来这样的话就找见什么呢出生在美国但是生活在欧洲的人我们再重复一下这个逻辑有点复杂你要对SQL不说的话可能想一会儿它还是recursive的多整个下面是recursive的多首先早见说recursive的早见说美国的地儿就是属于美国的市啊县啊这个地儿然后再早见说属于欧洲的地儿然后再早见所有出生在美国的人然后再找见所有生活在欧洲的人然后把它join一下找出来这个在这个database optimize的时候它可能会找见一个最小的site然后对这个site来说进行一个mapping就是这个的复杂度是什么呢这个复杂度是最小的site然后把这个加起来就是不会是层的关系它是一个最小的site加的关系但是这个最小的side和大小也相关,这里面最小的side是什么呢?最小的side,还挺复杂的不是很好优化,我自己直观看也不是很好优化如果我们看一下这个graph database的话graph database,你database creation的时候就可以这样子说我created一个,北美是location,然后它的content是什么,然后它name是北美然后这个create一个create一个usa作为location然后它name是什么,country是什么成为一个爱德华作为location它type是state是吧这个第一个type是大陆,第二个type是country第三个type是state然后create一个lucid所以爱德华是在美国里面的,是在北美大陆上的luci是出生在爱德华的那这样的话你就你相当于是visualize,你体现了Lucy出生在美国的爱德华然后但是生活在这个Europe然后你写matching card的时候这块matching card可能有七号,但是这块matching card是三号怎么呢?同一个person他出生在一个地方然后他recursively within us他生活在一个地方recursively within us然后把这个人select出来就可以了所以他这个复杂度可以看见非常直观就是在这个graph这个里面非常直观所以在选的时候当然就是之前说过就是没有一个好的一个solution是one size fits all根据你的use case来你什么时候选graph database当你这个是graph data model的时候如果你很多的use case是friends or friends or friends这种use case那你可能需要用graph database注意一下就是friends or friends or friends这种relationship可能用graph database如果不是这样的就是简单的一层的关系的话其实用MySQL是可以用SQL database是挺好的一个实践这个你像Facebook用的SQL,Facebook这个social network用的SQL然后这个样子然后雨泉问说有什么有名的product用在graph database,我还真不知道您可以看一下Neo4G,Neo4G肯定会把它写到这个商业宣传上,你search了Neo4G,有谁叫Neo4G把它变成这个这个上面我还真不知道谁在用就是特别大的有名的product我还真没有读到过但是是有用的因为neo4G它是有自己的它有个叫index-free graph working我记得叫index-free graph working就是它还是有用的neo4G 你就search你测试graph databaseneo4G算是最大的graph database然后好问说customer 2.0里面association底层是用graph database你把customer 2.0想的太好了Customer 2.0他的这个physical data model是没有换过的我读过他那个70页的那个那个ERD的他的Design Dock的他physical data model是没有换过的他是用scheme类似里面那个最原始的那个physical data model的他只是把自己的logical data model换掉了什么意思就是说你如果读
[55:00] 旧的Customer to Panel是Uber内部的一个管user的Data Model Concept它底层的这个DataModel是没有换过的,它还是用Schemeless旧的DataModel,它只是把这个从Physical Data Model读出来的Data,然后转化成Logical Data Model那块换了就把Logical那层换了,什么意思呢?如果你用,不管你是用Customer,就是用之前的Populus,就是旧的那个Customer方式,还是用Customer2.0你从这个database的角度来讲都没有变过,就是你始终还是读的同一个database,还是读的同一个table。但是你读完以后,相当于是你在这个mapper那层角度,我换了一下,以Mapper或API的角度换了一下,你之前是Rider, Driver, Partner, relationship,现在你就变成了User,这个logical data model了,所以这个你把customer图坏的时候想太好了但是这个它的设计其实是有道理的因为这个data migration做起来非常痛苦并且很容易出错啊这几个billion user的Migration做起来非常痛苦,非常容易出错。不Migration,用一样的 physical data model 本质上是没有问题的,我觉得从 engineering 设计角度来说是没有问题的。但是我个人觉得他的那个business signing point,就是比他那个带来的fundamental revolutionary change 要多,没有任何有趣的地方,我个人读了一下那个一二点。最后一点就是datalog,这个是declarative logical programming language,我之前写过一些prolog的东西,就是之前上programming language的时候写过一些prolog的东西。这个prolog就是你可以用prolog来实现就是Dequietive Logic Language,就是这个relationship不仅可以用MySQL实践,可以用Graph Database这个实践,也可以用Prolog实践,Prolog实践也是非常好奇的,它更像一种recursive的这种逻辑,比如说我们来看这种,他先升称了三个node,第一个node就是北美,前面这个是ID,后面是text,然后type它属于什么type然后又双双了美国,前面是ID,后面是Tax然后泰国的话属于country,然后说美国在北美之内然后这个 name type和 vz 都是 keyword然后这个紫色都是KWord的然后生存了一个爱德华,然后它是一个state,爱德华在美国之内,然后又定义了一个Lucy,Lucy是出生在爱德华的。然后它这个relationship就很有趣了,它是一个recursive relationship,就这块比如说它就定义入嘛,就是这个prologue的定义入。第一个入就是说,这个location呢,是第一个入是,我看第一个入试谢谢大家第一个书相当于是recursion的第一层,就是如果是fe return 什么这种感觉。第二个Rule是相当于是什么呢?就是你location可能在Vzinc,就是Vzinc这个recursion的定义啊,就是你这个location可能在什么location里面。比如说这个里面,你套用爱德华和这个爱德华和这个North America的话,你可以得出这个爱德华是在North America里面的。为什么呢?因为这个爱德华是在UIC里面的然后USA是在North America里面,所以第二个是Recursive这个关系,第一个是Recursive中止条件,第二个是Recursive关系,然后你取的结果呢就是描述型的吗描述你想要什么你要找一个person是吧描述你要找一个person,他出生在一个bone location然后呢,然后这个Bone location呢,是它生活在这个Bone location呢,是在这个Bone in这个里面。出生在一个Bone location,就是Recursor 出生在一个Bone location,然后他生活在一个Living location,Living location,Recursive 在那个地方,然后当你读的时候,你就可以把它变成一个Descriptive language,就是你找一个人,who,就是你要找的人,然后他出生在美国,生活在Europe这个Bond Location就是美国所以你叫recursively找建一个city,它出生的city可能就是recursively在美国里面,然后它这个生活的cursively在Europe里面。你要找见这么一个人第一次写的时候,这个mind side可能会稍微不一致,其实出版的是requestion的mind side好Prolog,Prolog用的地方还挺有趣的,Prolog有点像那种传统的AI,如果你在特别复杂的一个onstructured data 里面
[60:00] feel miserably. You have a failure to be very much But if you are in a虚拟 environment, and data is structured expected, Prolog performance is pretty good. You can do a small experiment in a small experiment. The things are regulated and expected. Prolog performance is pretty good. It's a very interesting thing. This is the last one. I'm not going to talk about database. Database is very long. This is very important. There are 24 hours later. Um, DataModel just talked about it. Do you have any questions? Thank you. No, that's just like this. I'm going to say that next week, I'll talk about YouTube, design YouTube. I won't talk about the following week, because I've been a lot of people. I'm not going to talk about it. Next week, I'll go to the next week and the next week. That's probably the plan. Thank you. Hello, I'm going to go to the hospital.