More  

小編的世界 優質文選 資料

Mysql、MongoDB?如何選擇合適的數據庫


2021年11月08日 - 資料小編  
   

碼農老K23:53工具主管,科技領域創作者

1.0 層次模型數據庫

用戶購買,生成訂單,訂單詳情裏有用戶購買的電子書:

一層一層鋪開,一對多,這是「層次模型數據庫」(Hierarchical Database)。

2.0 網狀模型數據庫

一筆訂單可以購買多本電子書,一本電子書也可以被多筆訂單購買:

這就形成了「多對多」的「網狀模型數據庫」(Network Database)。

上面講的兩種數據庫,也許你聽都沒聽過。

我們用的,是「關系模型」,而非上面的「層次模型」或者「網狀模型」。

為什麼?

你會說,這樣不方便遍歷所有訂單。

並不會,再加一個根節點就好:

你會說,這樣查找效率很低。

也不會,因為可以優化下數據結構,比如換成 B+ 樹。

為什麼我們從一開始就在用「關系模型數據庫」?

3.0 關系模型數據庫

無論是層次模型還是網狀模型,程序員看到的,都是實實在在的物理存儲結構。

查詢時,你要照著裏面的數據結構,用對應的算法來查;

插入時,你也要照著數據結構,用對應算法來插入,否則你就破壞了數據的組織結構,數據也就壞掉了。

因為我們都沒用過前面兩種數據庫,所以覺得「關系模型數據庫」(以下簡稱 RDB)的一切都理所當然,但其實,它做出了一個革命性的變革:

用邏輯結構(logical representation of data)代替物理結構(physical representation of data)

所謂「邏輯結構」,也就是我們經常看到的「表格」,User 是一張表格,Order 是一張表格,Book 又是一張表格,它們之間的關系,用 id 來關聯,這些 id,可能是 number 類型,也可能是 string 類型:

但你看到的,不一定就是實際的,你看到的只是讓你方便理解的「邏輯結構」,真實數據自然不是這樣按表格來存儲,表格無異於一個數組,數組查詢是很慢的。

真實的「物理結構」,也許還是像「層次模型」和「網狀模型」一樣,是複雜的數據結構。

但到底是怎樣的數據結構,你都無需關心,你只需把它想象成一張「表」去操作,就連可視化工具,都會幫你把數據可視化成表,來方便你理解。

Codd 的這種思想,其實就是經濟學裏提到的:分工產生效能。

程序員們不需要直接和物理結構打交道,只負責告訴數據庫,他想做什麼,至於數據是如何存儲、如何索引,都交給數據庫,最終他們看到的就是一張張特別直觀、特別好理解的 excel 表格。

而數據庫則把維護物理結構的複雜邏輯,交給了自己, 對程序員屏蔽了複雜的實現細節。

開發時寫的代碼少了,耦合性降低了,數據也不容易損壞,也就提高了生產效率(productive)。

一切能用同樣的耗能,帶來更多效能的技術,都會被廣泛使用。

NoSQL

那後來為什麼又有了 NoSQL 呢?

在 RDB 被發明的時代,軟件多用於大型企業,比如銀行、金融等等,人們對數據的要求非常純粹:准確、可靠、安全,讓數據按照期望,正確的寫入,不要給老子算錯錢就好,於是有了具有 ACID 特性的事務:原子性、一致性、隔離性和持久性。

那時候用網絡的人很少,通過終端來訪問客戶端的人,更少,自然的,數據庫的數據量和訪問量都跟現在沒法比,一台機器,足矣,最多再來個一主多從:

後來,你知道的,每個人手裏都有個手機,每分每秒,都有成千上萬的數據,寫入你的數據庫、從你的數據庫被查出,於是有了「分布式」,有了 BASE 和 CAP。這時候,RDB 就會發現,自己之前的那一套 ACID,竟然有點作繭自縛了:

為了保證事務的隔離性,要進行加鎖,在分布式的環境下,就要對多台機器的數據進行加鎖;為了保證事務的原子性,在機器 A 的操作和在機器 B 的操作,要麼一起成功,要麼一起失敗;……

這些都要去不同節點的機器進行通訊和協調,實現起來非常複雜,而且要付出更多的網絡 IO,影響性能。

ACID 在分布式系統上實現起來就會變得難以實現,即使實現了,也要付出很大的性能成本,於是才有了後來的各種「分布式一致性協議」,Paxos、Raft、2PC …… 而 Mysql 也提供了各種方案來實現分布式,當然,這些方案自然是很複雜的,比如 「NDB Cluster」 :

而 NoSQL 則沒有這麼多承諾,它的一致性,一般都是最終一致性,當然你可以選擇強一致,那自然就要付出點性能作為代價,當然你還可以弱一致,這樣會更不安全,但是更快,一切取決於你對數據的要求。

除此之外,RDB 的「數據庫範式」(Database Schema),也成了限制擴展性的瓶頸。為了避免數據冗餘導致的各種問題(占用空間、刪除異常、更新異常等等),我們在設計關系模型時,通常都是按照最小單位來設計的。

什麼叫最小單位,比如用戶有地址和愛好,那麼在正確設計的關系模型(比如 3NF)裏,這就是三張表:

如果這三張表被分散在不同的機器,那進行關聯查詢時,就需要多次跨機器的通訊;

而對於 NoSQL,這三類信息,都可以利用 Json 格式的數據,將它們存放在一起:

完整的存儲進去,完整的取出來,不需要額外的操作。

NoSQL 比 RDB 有更強的擴展性,可以充分利用分布式系統來提升讀寫性能和可靠性。

這不是誰設計好壞的問題,而是跟他們要解決的問題有關:RDB 誕生於互聯網萌芽的時代,那時數據的准確、可靠是最重要的,而 NoSQL 誕生於互聯網快速發展普及的時代,大數據、分布式、擴展性成了數據庫的另一個重要特性。

總結一下:

RDB 首先得是准確、可靠,然後才向更高的「可拓展性」發展;而 NoSQL 生而分布式,可拓展性強,然後才向更高的「准確性」發展。

NoSQL ,not only SQL,其實就是對那種打破了 RDB 嚴格事務和關系模型約束的哪些數據庫的泛指,而隨著要解決的問題的不同,又誕生了各種各樣的 NoSQL。

首先是「列式數據庫」(Column-oriented DBMS),數據量上去了,我們想分析網站用戶的年齡分布,簡單說,就是你需要對同一個特征進行大數據量的分析統計,於是把原來 RDB 的「按行存儲」的範式打破,變成了「按列存儲」,比如 HBase;

然後你發現有些數據變動不是很大,但是經常需要被查詢, 查詢時還要關聯很多張表,於是你把這些來自不同表的數據,揉成一個大對象,按 key-value 的格式存起來,比如 Redis;

再後來你需要對博客內容進行相關性搜索,傳統 RDB 不支持相關性搜索,最重要的,還是擴展性差,增加機器的帶來邊際效益有限,於是有了「全文搜索引擎」,比如 Elasticsearch;

除此之外,還有「文檔數據庫」、「圖形數據庫」……

沒有一種數據庫是銀彈。

總結

這篇文章的題目是「如何選擇數據庫」,這是困擾很多人的問題,那麼多數據庫,到底要選什麼好?

可是當你問出這樣一個問題時,其實你是在問一種「手段」。我現在要做這樣一個需求,用什麼數據庫可以幫我實現它?

但其實你需要的不只是一種「手段」,因為如果對方甩給你一個冷冰冰的名字,Mysql、Elasticsearch、MongoDB,你肯定會問,憑什麼?

你需要的,是一種「解決方案」。如果你需要數據十分嚴格准確,分毫不差,那我會推薦你采用「事務」和「關系模型」來處理數據;如果你需要數據能夠被大量讀取和寫入,那我會推薦你擴展性強的「分布式」;如果你的數據經常是整個讀取、整個更新的,那「關系模型」就沒有「文檔模型」適合你。

「事務」、「關系模型」、「分布式」、「文檔模型」等等,這些就是「解決方案」,知道用什麼「解決方案」,用哪個數據庫,自然水到渠成。

正如一位大牛說的:

設計實踐中,要基於需求、業務驅動架構。無論選用 RDB/NoSQL,一定是以需求為導向,最終數據存儲方案必然是各種權衡的綜合性設計。

用戶不會因為你用了 Mysql 或者 MongoDB 而使用你的軟件,畢竟絕大多數用戶都不知道 Mysql 和 MongoDB 是什麼玩意。

  大家在看