有了 MySQL 爲何要用 NoSQL?

回覆 PDF 領取資料html

這是悟空的第 87 篇原創文章
mysql

本文來自個人一次真實面試經歷。web

這家公司的真名就叫作「三藏」,和個人名字「悟空」很契合,唐三藏給悟空面試,合情合理,還帶有一絲趣味,因此我就去面試了。三藏公司是一家小廠,技術負責人面的我,欲知面試結果,文末揭曉面試

本文主要內容以下:sql

1、MongoDB 和 MySQL

1.面試官:看你的簡歷上寫了 MongoDB,說下 MongoDB 和 MySQL 的區別吧。mongodb

其實對於這個問題,我事先有準備,簡歷上寫了 MongoDB,面試官確定會問 MongoDB 和 MySQL 的區別。數據庫

MongoDB 是非關係型的數據庫(NoSQL),屬於文檔型數據庫,文檔數據庫就是爲了解決關係數據庫帶來的問題。最大的特色是 no-schema,能夠存儲和讀取任意的數據。小程序

存儲的數據格式就是 JSON(或者 BSON)。JSON 格式咱們都比較熟悉,好比 Rest API 請求返回的 Response 就是 JSON 格式的。JSON 格式的數據和 XML 格式的區別是 JSON 更簡單,沒有那麼多的標籤來定義字段名。也就是說 JSON 是自描述的。另外 JSON 格式存進 MongoDB 中後,即便讀取一個 JSON 中不存在的字段也不會致使 SQL 那樣的語法錯誤數組

MongoDB 優勢

因爲文檔數據庫具備 no-schema 特性,用起來有如下幾個明顯的好處緩存

(1)新增的字段不會出錯。

好比用戶表增長一個暱稱的字段,不須要像關係型數據那樣執行更新表結構的語句。咱們直接查詢這條文檔出來就能夠看到新增的字段了。

(2)查詢歷史數據不會出錯。

上面提到新增了一個暱稱字段,可是歷史數據中是沒有這個字段,若是查詢歷史數據,則返回的數據中不會有這個字段,雖然查詢不會報錯,可是取值時,會返回 null。若是業務代碼中用到了暱稱字段,則須要作兼容性處理。

(3)輕鬆存儲複雜數據。

由於是用 JSON 存儲,而 JSON 又能夠表示複雜的數據結構,好比字段能夠存數組,字段能夠嵌套字段,並且能夠存不少字段。換作 MySQL,則須要設計幾張表來存。MongoDB 存數據的結構,特別適合電商這種業務場景,好比兩種不一樣的商品,屬性差異就很大,可是用 JSON 存就能夠輕鬆應對。

可是文檔數據庫有什麼缺點呢 ?

MongoDB 缺點

(1)目前 4.0 之前不支持多文檔事務。

結合 MongoDB 文檔模型內嵌數組、文檔的支持,目前的單文檔事務能知足絕大部分開發者的需求。爲了讓 MongoDB 能適應更多的應用場景,讓開發變得更簡單,MongoDB 4.0 將支持複製集內部跨一或多個集合的多文檔事務,保證針對多個文檔的更新的原子性。而在將來的 MongoDB 4.2 版本,還會支持分片集羣的分佈式事務。

咱們來看下 MongoDB 不一樣版本支持的功能:

MongoDB 的不一樣版本

MongoDB 的事務接口很是簡單,開發者只須要將須要保證原子性的更新序列放到一個 session 的 開始事務提交事務之間便可。下面是 Java 使用 MongoDB 事務的示例代碼:

(2) 不支持關聯查詢。

咱們都知道 MySQL 是支持關聯查詢的,也就是能夠執行 Join 操做。好比有兩張表:用戶表和訂單表,訂單表中有用戶的 id,且性別只存在用戶表中。若是想購買了手機的男性用戶,用關聯查詢,一步就能搞定。可是若是用 MongoDB,則須要查兩次,先查詢訂單表中購買手機的用戶,再查詢這些用戶中哪些是男性。

2、關係型數據的缺點

2.面試官:這個項目爲何不用關係型數據庫?關係型數據庫有哪些缺點?

順着面試官的思路,能夠知道面試官想問的是關係型數據庫有哪些不足之處。

關係型數據庫的不足之處

(1)存儲的是行記錄

不能存儲數組、嵌套字段等格式的數據。

(2)擴展表結構不方便

操做不存在的列會報錯,而增長列又須要執行 SQL 語句才行。並且修改時須要特別注意,由於更新表時會長時間鎖表,這對線上環境可能形成嚴重影響。

(3)佔用內存高

關係型數據庫在對大量數據的表進行統計之類的運算時,佔用內存會很高,由於它即便只針對某一列進行運算,也會將整行數據從存儲設備讀入內存。

(4)全文搜索性能差

相似於 MySQL 的關係型數據庫,只能用 like 進行整表掃描的匹配,效率很低。現現在,有不少場景須要支持模糊匹配,並且必須支持高效查找。好比查詢包含關鍵字的日誌信息,又或者是根據某個商品關鍵字查詢商品列表。

針對以上的不足之處,咱們這個項目用了兩種非關係型的數據存儲方案:MongoDB 和 ElasticSearch。

3、NoSQL 的分類和特色

3.面試官:你知道的有哪些 NoSQL 數據庫?分別有什麼特色?

NoSQL(NoSQL = Not Only SQL ),意即"不只僅是SQL"。

我知道的有 Redis、MongoDB、HBase、全文搜索引擎 Elasticsearch。他們是不一樣的非關係型存儲方案。

K-V 存儲型

好比 Redis,它能夠用 K-V 鍵值對的方式來存儲數據,而存儲的值能夠有好幾種格式,如 string、hash、list、set、bitmap 等。

文檔存儲型

好比 MongoDB,存儲的 JSON 格式的文檔,解決了關係型數據庫的表約束的問題,好比查詢不存在的字段會報錯。另外也解決了部分存儲格式的問題,因JSON 能夠表示數組,還能夠嵌套字段存儲。

列式存儲型

好比 HBase,按照列來存儲數據,解決了大數據場景下的 I/O 問題。

關係型數據庫按照來存儲數據,因此稱做行式數據庫。按照來存儲有如下優點:

  • 讀一行數據就能讀取到多個列,只須要一次磁盤操做就能把多個列的數據讀取到內存中。
  • 寫一行數據能夠對多個列進行寫操做,保證了行數據的原子性和一致性。而對列式存儲的多列寫操做,可能會致使有些列成功,有些失敗,產生數據的不一致。

全文搜索引擎

這個用到的最多的地方就是日誌系統,還有搜索商品信息等相似場景。以下圖所示的電商網站。

搜索手機

咱們項目中用到日誌搜索就是利用 ELK。

Elasticsearch 就是 ELK 中的 E。Elasticsearch 就是全文搜索引擎,注意:他是一種 NoSQL 方案,並非 NoSQL 數據庫。

Logstash 就是 ELK 中的 L。它是 Elastic Stack 的核心產品之一,可用來對數據進行聚合和處理,並將數據發送到 Elasticsearch。Logstash 是一個開源的服務器端數據處理管道,容許您在將數據索引到 Elasticsearch 以前同時從多個來源採集數據,並對數據進行充實和轉換。

Kibana 就是 ELK 中的  K。是一款適用於 Elasticsearch 的數據可視化和管理工具,能夠提供實時的直方圖、線性圖等。

以下圖所示:

搜索日誌

傳統的關係型的數據庫主要是經過索引來進行快速查詢,但若是放在全文搜索的場景下,就行不通了。

咱們來看看爲何關係型數據庫很難作到高效的全文搜索:

  • 由於在全文搜索中,搜索的條件是能夠隨意排列組合的,好比字段 A、B、C,能夠排列成 6 種,若是要用索引來支持快速查詢的話,則須要建立多個索引,這是很是麻煩的,同時,多個索引對數據的插入效率也是有影響的。
  • 模糊匹配只能用 like 查詢,而 like 查詢是整表掃描,效率是很是低的。

以前我寫過一篇 Elasticsearch 原理的:《別隻會搜日誌了,求你懂點原理吧》,經過倒排索引實現高效的全文檢索。下面舉個倒排索引的例子給你們看看:

假如數據庫有以下電影記錄

1-大話西遊

2-大話西遊外傳

3-解析大話西遊

4-西遊降魔外傳

5-夢幻西遊獨家解析

分詞,將整句分拆爲單詞

序號 保存到 ES 的詞 對應的電影記錄序號
A 西遊 1,2, 3,4, 5
B 大話 1,2, 3
C 外傳 2,4, 5
D 解析 3,5
E 降魔 4
F 夢幻 5
G 獨家 5

檢索:獨家大話西遊

獨家大話西遊 拆分紅 獨家大話西遊

ES 中 A、B、G 記錄 都有這三個詞的其中一種, 因此 1,2, 3,4, 5 號記錄都有相關的詞被命中。

1 號記錄命中 2 次, A、B 中都有 ( 命中 2 次 ) ,並且 1 號記錄有 2 個詞,相關性得分:2 次/2 個詞=1

2 號記錄命中 2 個詞 A、B 中的都有 ( 命中 2 次 ) ,並且 2 號記錄有 2 個詞,相關性得分:2 次/3 個詞= 0.67

3 號記錄命中 2 個詞 A、B 中的都有 ( 命中 2 次 ) ,並且 3 號記錄有 2 個詞,相關性得分:2 次/3 個詞= 0.67

4 號記錄命中 2 個詞 A 中有 ( 命中 1 次 ) ,並且 4 號記錄有 3 個詞,相關性得分:1 次/3 個詞= 0.33

5 號記錄命中 2 個詞 A 中有 ( 命中 2 次 ) ,並且 4 號記錄有 4 個詞,相關性得分:2 次/4 個詞= 0.5

因此檢索出來的記錄順序以下

1-大話西遊 ( 關性得分:1 )

2-大話西遊外傳 ( 相關性得分:0.67 )

3-解析大話西遊 ( 相關性得分:0.67 )

5-夢幻西遊獨家解析 ( 相關性得分:0.5 )

4-西遊降魔 ( 關性得分:0.33 )

Elasticsearch 與 mysql 的對比

序號 Mysql Elasticsearch
1 Mysql 服務 ES 集羣服務
2 數據庫 Database 索引 Index
3 表 Table 類型 Type
4 記錄 Records ( 一行行記錄 ) 文檔 Document ( JSON 格式 )

另外的 NoSQL 還有圖形數據庫,這裏不作展開。

關係型和 NoSQL 怎麼選?

4.面試官:關係型和 NoSQL 怎麼選呢?

關係型和NoSQL數據庫的選型,考慮幾個指標,數據量、併發量、實時性、一致性要求、讀寫分離、安全性、運維性等。根據這些指標,軟件系統可分紅幾類。

  • 管理型系統,如運營類系統,首選關係型。
  • 大流量系統,且多字段、數據量增加快,首選 NoSQL。
  • 日誌型系統,首選 Elasticsearch
  • 搜索型系統,指站內搜索,非通用搜索,如商品搜索,首選 Elasticsearch。
  • 事務型系統,如庫存、交易、記帳,選關係型+緩存+一致性協議。
  • 離線計算,如大量數據分析,首選列式數據庫。
  • 實時計算,如實時監控,能夠選時序數據庫,或列式數據庫。

面試結果:技術負責人以爲還行,但 HR 今天不在,等 HR 下次通知吧。後續就沒通知了。完。

參考資料: 

https://mongoing.com/archives/5560 

https://time.geekbang.org/column/article/8377 

https://dzone.com/articles/history-databases-%E2%80%9Cno-tation%E2%80%9D 

https://www.runoob.com/mongodb/nosql.html

- END -

寫了兩本 PDF,歡迎下載學習。

週日寫的文章《大佬,你的網站崩了》忘了嵌入視頻,此次給你們看下。

文末閱讀原文也能夠進入到這個網站。

我是悟空,努力變強,變身超級賽亞人!

本文分享自微信公衆號 - 悟空聊架構(PassJava666)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索