MongoDB 全方位對比 MySql

原創於【模稜博客】 http://www.flammulina.com

1.介紹

可以說,作為IT專業人員,我們正處於數據管理時代的黃金時代。隨著我們的軟件系統變得越來越複雜且分佈更廣,受到無數可擴展性和可用性要求的推動,多年來使用的傳統解決方案開始落後。

本教程的目標是提供兩種數據管理解決方案的公平概述:由MySQL代表的成熟和廣泛使用的關係數據庫以及該塊MongoDB上的新成員,後者又代表新一代數據存儲。這決不是與最終明確的贏家的戰鬥。相反,其目的是通過探討MySQL和MongoDB的功能,幫助開發人員做出選擇並找到適合他們應用程序的正確選擇,討論每個人的不同保證和限制。

MongoDB 全方位對比 MySql

2. RDBM系統的優勢

數據管理軟件的發展歷史並不是一個特別令人興奮的時間。在相當長一段時間內,關係數據庫管理系統發揮了領導作用,多年來,選擇很明顯,無論是MySQL,PostreSQL還是Oracle,僅舉幾例。SQL(及其特定於供應商的方言)是查詢關係數據存儲的事實上的標準,根據定義,每個後端軟件開發人員都必須學習和理解其至少一些基本知識。直到最近,當一系列新的數據管理系統出現時,它的表現非常出色,這種現象也被稱為NoSQL(或非唯一SQL)運動。

MongoDB 全方位對比 MySql

3. NoSQL運動的新時代

現代軟件系統在數據量和請求/事務吞吐量要求方面面臨的挑戰表明,關係數據存儲常常成為瓶頸,因此對整體系統可擴展性施加限制。傳統上,解決這個問題的方法只是購買一個更大的盒子(所謂垂直可擴展性),但是在某些時候,付出的代價變得非常高,使得整個系統的代價非常昂貴和不切實際。

業界正在積極研究構建複雜分佈式系統的更便宜的方法,而不是利用橫向可伸縮性。它還意味著提供關係數據存儲的替代方案,並可以水平擴展。那一刻,當NoSQL運動開始時。

4.表格與文檔vs圖表與鍵/值

一個關係型數據模型代表的元組和關係上的所有數據(更好地稱為表)。結構化數據非常適合這種模式,很長一段時間沒有其他可行的替代方案存在。隨著NoSQL的運動,許多替代數據模型被開發出來,誕生了大量的專用數據存儲系統。

在NoSQL的解決方案,可以在幾個不同的類別進行分類。文檔數據存儲設計用於存儲,查詢和管理文檔(半結構化數據)。這個類別中較成熟的代表包括CouchDB,Couchbase,MongoDB,OrientDB和HyperDex。鍵/值數據存儲設計用於存儲,查詢和管理關聯數組(也稱為字典或散列)。

這個類別中使用最廣泛的代表包括DynamoDB,FoundationDB,HyperDex,MemcacheDB,Redis,Riak,Aerospike和OrientDB。圖形數據存儲設計用於高效地存儲和操作圖形結構。這一類的著名代表包括Neo4J,InfiniteGraph,GraphBase和OrientDB。最後但並非最不重要的是,寬列數據存儲正在採用混合方法(結合關鍵/值數據存儲的一些特性和傳統的關係數據存儲)。這一類最先進的代表包括Accumulo,Cassandra和HBase。

請注意,上面介紹的不同NoSQL數據存儲列表遠遠沒有完成,它只包含最知名和廣泛使用的名稱,但還有更多。

MongoDB 全方位對比 MySql

5. MySQL和MongoDB:有意識的決定

引言足夠了,讓我們繼續討論更實用的東西。在本教程的這一部分,我們將使用MySQL和MongoDB來看看應用程序開發過程的各個方面,同時也花費一些時間來討論部署和監視。我們的目標是討論每個數據存儲所做的權衡和設計決策,並分析它們如何改變我們開發應用程序的方式。另外,本教程的另一個目的是在考慮到應用程序體系結構,數據訪問模式和存儲需求的情況下,協助做出決定,何時MongoDB可能比MySQL更好(反之亦然)。

正如我們現在所說的,MongoDB是一個文檔數據存儲。它存儲分組到集合中的JSON樣式的文檔。在MongoDB數據模型層次結構的頂部是一個數據庫(請參閱官方文檔以獲得全面的詳細信息)。目前的生產就緒版本的MongoDB是3.0.4。

從另一方面來說,MySQL是關係數據存儲。數據存儲在包含列的表格中。表格被分組到數據庫中(請參閱官方文檔以獲得全面的詳細信息)。當前生產就緒版本的MySQL是5.6.25。

MySQL支持多個存儲引擎,每個存儲引擎都有自己的目的,並且具有其他存儲引擎不具備的一些功能。在本教程中,我們假設使用InnoDB存儲引擎,因為它是默認和最通用的引擎,推薦使用,除了專用用例。

5.1。強制模式與無模式

作為關係數據存儲的MySQL需要一個嚴格的數據模型模式:所有的表都應該使用定義的列來創建。只有這樣才能使用SQL語言存儲和查詢數據。由於每次需要修改數據模型時都會使開發和部署過程複雜化,因此應該首先更改模式,然後再遷移數據。下面是使用MySQL shell和SQL語言創建新數據庫,新表並向其中插入一行所需的典型步驟示例:

MongoDB 全方位對比 MySql

相比之下,MongoDB不會對集合中存儲的文檔施加任何模式。應用程序負責處理這個問題,MongoDB限制的唯一事情就是支持的數據類型。它顯著加快了開發過程,因為MongoDB可以立即用於存儲任何形狀的JSON文檔。

文檔的結構可以隨著時間的推移而發生變化,並且不同代的文檔可以共存於同一個集合中。如果需要,應由開發人員決定如何執行數據清理或遷移。讓我們來看看如何使用MongoDB外殼完成創建新數據庫,新集合和向其中插入一個文檔的相同步驟:

MongoDB 全方位對比 MySql

值得一提的是,即將發佈的5.7版本的MySQL(目前處於候選版本階段)引入了本機JSON支持。隨著這種新的JSON數據類型的引入,將有可能在MySQL中結合強制模式和無模式數據。

MongoDB 全方位對比 MySql

5.2。標準化與複製

關係數據庫世界中的規範化是組織表以最小化數據冗餘的過程。它涉及將表分解為不冗餘(和更小)表而不丟失數據。它還假定在舊錶中定義引用新鍵的主鍵的外鍵。例如,這是在MySQL中創建兩個表的方式,books表引用authors表:

MongoDB 全方位對比 MySql

MongoDB的規範化已經過時了。相反,仔細的數據建模和一定程度的數據重複是最大限度地利用文檔數據存儲的方法。它也成為應用程序的責任來決定數據重複的級別並在修改的情況下保持所有數據片段同步。例如:

MongoDB 全方位對比 MySql

5.3。關係與參考

在規範化數據庫中,SQL中的JOIN子句通常用於合併來自兩個或多個MySQL表的記錄(還有其他技術,但總體上它們導致相同的結果)。例如:

 SELECT * FROM books b INNER JOIN authors a ON a.id = b.author_id;

MongoDB支持文檔引用,但不支持連接:為了解析引用,應該執行額外的一個或多個查詢(導致關係世界N + 1查詢問題臭名昭著)。例如,在下面的代碼片段中,我們從書籍集合中插入對作者集合的引用,而不是嵌入作者的詳細信息:

MongoDB 全方位對比 MySql

必要的往返行程是支付無模式靈活性的代價。但是,正如我們在規範化與複製部分中已經提到的那樣,某些數據重複級別和對數據訪問模式的仔細分析可能會緩解這個問題。

MongoDB 全方位對比 MySql

5.4。交易與原子更新

交易是數據管理系統根據其數據執行的工作的邏輯單元。事務的重要性被封裝到它的基本屬性中:事務必須是原子的,一致的,隔離的和持久的(也被稱為ACID模型)。MySQL是一個完全事務關係數據存儲,使其成為不能容忍數據丟失或不一致的任務關鍵型應用程序的完美選擇。但是,事務不是免費的:它們大大限制了數據存儲的水平可伸縮性,MySQL也不例外。

MongoDB不支持事務保證。相反,它支持單個文檔級別的原子更新。這意味著當一個更新操作修改多個文檔時,每個文檔的修改都是原子的,但整個操作不是原子操作,其他操作可能會交織。值得一提的是,可以在MongoDB之上實現類似事務的語義(使用兩階段提交技術),但它需要非常複雜的實現。

5.5。SQL vs JSON

SQL是一種特殊用途的編程語言,用於管理關係數據庫管理系統中保存的數據。它是MySQL支持的唯一查詢語言,並增加了一些特定於供應商的擴展。儘管簡單,但SQL是一種非常強大的語言,它基本上由兩部分組成:數據定義語言(DDL)和數據操作語言(DML)。我們已經看到了很多例子,但讓我們看看從表格中選擇行的最簡單也是最有用的例子:

 SELECT * FROM books;
SELECT * FROM books WHERE title LIKE "%MySQL%";

在MongoDB中,所有東西都是一個文檔,用JSON表示。MongoDB沒有專門的語言來管理文檔,而是採用了非常不同的方法。文檔操作或查詢使用非常豐富的一組操作符來描述,這些操作符使用JSON結構相互組合,與其他任何文檔一樣。這種統一的表示形式非常強大,表達和易於理解,而且不需要學習另一種編程語言。大多數操作員都是不言自明的直觀的,例如:

MongoDB 全方位對比 MySql

5.6。存儲過程與腳本

存儲過程是關係數據存儲的服務器端可用的一種特殊例程。存儲過程可以用不同的編程語言實現,但大多數情況下,它們都是使用SQL或其特定於供應商的方言編寫的,這是MySQL的情況。通常,存儲過程通過在服務器上直接執行某些邏輯來幫助提高應用程序的性能,這就需要在服務器和客戶端之間發送更少的信息。例如,下面是一個非常簡單的MySQL存儲過程:

MongoDB 全方位對比 MySql

MongoDB以服務器上執行JavaScript代碼的形式支持服務器端腳本。這些服務器端腳本可能與存儲過程相似,但實現不僅僅是簡單的腳本,因為它支持map / reduce範式,最初由Google填充,並廣泛用於大數據分析。本質上,通過提供map / reduce命令的腳本,可以跨多個MongoDB數據存儲實例並行處理大型和超大型數據集。讓我們看一下非常天真的map / reduce腳本示例,它可以計算出有多少書籍的標題中包含“MySQL”字符串:

MongoDB 全方位對比 MySql

與MySQL存儲過程示例相比,MongoDB看起來過於冗長和複雜。然而,一旦map / reduce範例的概念變得更加清晰,這個例子將會看起來非常簡單,為應用許多數據處理,探索和分析技術開闢了一個全新的前沿。

5.7。GROUP BY與聚合

在數據管理領域,聚合函數是一個函數,其中多個數據記錄的值根據特定的聚合準則分組在一起,因此產生更重要的意義或度量的單個值。在SQL語言定義了一組用於執行聚合特定條款:GROUP BY和HAVING。標準分組函數集包括AVG(),COUNT(),MAX(),MIN(),STD(),SUM()。讓我們看看MySQL shell中的GROUP BY示例:

MongoDB 全方位對比 MySql

MongoDB提供了一組專門的聚合操作,它處理文檔並返回計算(或聚合)的結果。彙總操作將來自多個文檔的值組合在一起,並且可以對分組數據執行各種操作以返回單個結果。MongoDB中的聚合可以通過兩種方式完成:使用聚合管道或單用途聚合方法和命令。

讓我們看看我們準備展示MySQL聚合的同一個例子,這次使用MongoDB的聚合管道:

MongoDB 全方位對比 MySql

我們在“ 存儲過程與腳本”部分討論過的map / reduce命令也可以視為一種聚合方式。

MongoDB 全方位對比 MySql

5.8。聚類和分片/分區

如今,數據量呈指數增長,數據存儲的單一物理實例通常無法持續並以可接受的速度管理如此大量的數據。集群技術可以使許多個人計算實例一起工作。就數據存儲而言,集群與數據分片/分區並行進行,這是一種將大量數據分散到多個數據存儲實例的技術。

一段時間以來,MySQL已經可以在MySQL Cluster版本中使用,該版本聲稱是可寫入擴展的實時ACID兼容事務數據存儲。MySQL Cluster建立在分佈式多主架構之上,支持自動分片/分區和水平擴展以提供讀寫密集型工作負載。

從歷史上看,MySQL Cluster的信譽太複雜,很難配置,監視和維護。與獨立的MySQL部署相比,數據模式的設計應考慮數據分片/分區,否則數據存儲的性能將受到很大影響。最後,MySQL Cluster與常規的MySQL發行版相比有很多限制。

MongoDB文檔數據存儲使用分片群集的概念支持分片/分區。MongoDB分片/分區的強大之處在於它具有簡單易用的配置。它橫向很好地縮放,但有很多限制需要注意。

MongoDB 全方位對比 MySql

5.8.1。複製

複製是保持數據安全(通過將其複製到多個數據存儲實例中)的關鍵技術,並且在許多情況下用於提高處理此數據的應用程序的可伸縮性和容錯性。MySQL支持傳統的主/從複製,默認情況下它是異步的,但是也可以使用半同步和延遲複製模式。

MongoDB通過引入副本集來處理複製。基本上,它是主/從複製,但MongoDB使用一點點不同的術語。稱為主服務器的主服務器接收所有寫入操作和從服務器,稱為輔助服務器,從主服務器應用操作。副本集支持的最大功能之一是自動故障轉移:當主節點不與副本集的其他成員進行通信時,副本集將嘗試選擇另一個成員以成為新的主節點。

公平地說,可以使用自動故障轉移來配置MySQL主/從複製,但在MySQL社區中有一些關於此功能的疑慮和討論。

5.9。全文搜索

由於很長一段時間,MySQL支持使用特殊類型的索引實現的全文索引和搜索。僅在自MySQL 5.6發佈分支以來,才有可能在InnoDB存儲引擎上提供全文索引支持,這一點很重要。

有趣的是,全文搜索的MySQL可以使用自然語言搜索(短語搜索),布爾搜索(搜索項的搜索)的哪裡話來搜索可能被標記為“必須存在”或“必須是不存在的”,並查詢擴展搜索(對自然語言搜索進行輕微修改)。但是,目前全文索引在群集MySQL部署中不受支持(請參閱Clustering and Sharding / Partitioning部分以獲得關於MySQL Cluster的簡要討論)。讓我們看看一個簡單的例子:

MongoDB 全方位對比 MySql

不久前在MongoDB中引入了全文搜索支持。與MySQL類似,它使用字符串內容(或字符串數​​組)的特殊類型的索引來實現。MongoDB也支持短語搜索,術語搜索和布爾搜索作為這些的組合。它很容易使用和優雅實施的功能,但不是沒有限制。不幸的是,目前MongoDB不能控制指定字段的子集來執行全文搜索:它總是匹配全文索引中包含的所有字段。讓我們來看看MongoDB全文搜索的實際操作:

MongoDB 全方位對比 MySql

5.10。發展

當涉及到開發時,MySQL提供了大量的連接器,可以用來從您選擇的大多數主流編程語言與服務器進行通信。關於Java開發,MySQL包含一個符合JDBC 3.0和JDBC 4.0規範的JDBC驅動程序。

雖然很少遇到使用直接JDBC接口與關係數據存儲進行通信的代碼(許多框架都是為了方便而構建的),但知道涉及的內容是很好的。讓我們看看下面的代碼片斷,它連接到MySQL並執行一條SELECT語句:

MongoDB 全方位對比 MySql

它看起來很冗長並且充滿了異常處理。MongoDB反過來擁有豐富的驅動程序生態系統,除主流語言外,還包括Erlang,Go,Node.js和Scala的驅動程序。MongoDB有自由提出自己的規範,正在開發下一代驅動程序,並快速地將現有實現與業內最新趨勢相適應(ReactiveMongo:MongoDB的ReactiveMongo:ReactiveMongo的非常好的例子) 。

舉一個例子,讓我們看看使用Java和Morphia驅動程序連接到MongoDB的一種方法(假設我們有Book和Author數據模型類):

MongoDB 全方位對比 MySql

從歷史上看,Java中的JSON支持是非常好的,因為它提供了豐富的社區支持庫,從而使JSON文檔轉換為Java類(和後面)毫不費力。

如果說Java社區已經開發了相當多的不同的對象關係映射框架(ORM)來從低級JDBC接口中抽象出來是不公平的,這實際上可以像MongoDB的例子那樣簡潔地編寫代碼。然而,理解它們會增加現有應用程序的複雜性非常重要。

5.10.1。部署

雙方的MySQL和MongoDB的可在大多數主要操作系統。在大多數情況下,MySQL是從特定於平臺的軟件包安裝的,並且需要對系統進行特權訪問。雖然可下載的檔案也可用,但根據操作系統,配置和版本(例如MySQL Cluster),安裝可能會變得相當複雜和不直觀(但可能不需要對系統進行特權訪問)。

相反,MongoDB在大多數情況下是作為可下載的檔案分發的,可以立即解壓縮並使用。通過要求最低限度的配置,合理的默認值在這裡扮演著重要的角色,只需運行MongoDB服務器並開始用文檔填充數據存儲。


可以公平地指出,隨著集裝箱化和Docker的部署程序(我們習慣於這樣)的格局正在發生非常迅速的變化。從傳統的基於軟件包的發行版轉移到預配置的容器,可以將可安裝的軟件包和下載 – 解壓縮運行的模型展平:所有東西都會成為一個圖像,作為獨立的容器運行,並以毫秒為單位運行。

更不用說,許多雲提供商(AWS,Cloud Foundry,Open Shift等)都提供了針對MySQL和/或MongoDB的軟件即服務產品,可以處理所有配置,基礎架構和可擴展性細節。

5.11。監測和診斷

顯然,監控是任何數據存儲管理過程的關鍵組成部分。有相當多的商業解決方案可用於監控您選擇的數據存儲,但讓我們討論可作為MySQL和MongoDB發行版一部分提供的解決方案。

MySQL有幾種方法來執行監視和診斷。首先,它是SHOW ENGINE STATUS命令。其次,MySQL支持性能模式,這是一個用於監視MySQL服務器執行的低級功能。最後,MySQL支持DTrace探測器(不受每個操作系統的支持),這些探測器旨在提供有關MySQL服務器內查詢執行的信息以及在該過程中正在使用的系統的不同區域。

MongoDB發行版包含許多命令行實用程序,可以快速檢索有關每個數據存儲實例的性能和活動的統計信息。不僅如此,每個運行的MongoDB實例還提供了一個Web界面,通過簡單的網頁顯示診斷和監控信息。最後,MongoDB包含許多命令,通過shell連接到數據庫,以瞭解數據庫的狀態。

5.12。安全

MySQL使用基於權限的安全模型。所述的主要功能的MySQL的權限系統是認證用戶,並與特權用戶特定數據庫上相關聯(如CREATE,DROP,SELECT,INSERT,UPDATE,DELETE 等)。

到目前為止,MySQL特權系統不支持的東西很少:無法明確指定給定用戶應該被拒絕訪問,也無法指定用戶有權創建或刪除數據庫中的表,但不能創建或者丟棄數據庫本身。在傳輸層上,MySQL使用TLS v1.0協議使用SSL(安全套接字層)支持客戶端和服務器之間的安全(加密)連接。


MongoDB的安全功能包括認證,授權和審計。其基礎是基於角色的訪問控制,具有靈活的特權。值得一提的是,MongoDB通過定義一組內置角色為用戶定義的角色提供了基礎。也可以使用TLS / SSL(傳輸層安全/安全套接字層)來加密所有MongoDB的網絡流量,以確保它只能由預期的客戶端讀取。

MongoDB 全方位對比 MySql

5.13。權衡,而不是戰鬥

正如我們所看到的,MySQL和MongoDB具有相同的共同目標:為其用戶提供全面的數據管理解決方案。然而,他們每個人接近這個目標的方式都非常不同。從一方面來說,我們看到了相當成熟和經過測試的關係數據存儲。從另一方面來說,我們遇到了年輕但迅速成熟的文檔數據存儲,非常適合某些類型的現代Web應用程序。

正如本教程中多次提到的那樣,這不是一場戰鬥,我們也不是在尋找贏家。相反,我們正在尋找更適合您應用需求的解決方案。更重要的是,異構數據存儲基礎設施比現在的例外變得更為常見:例如,MongoDB可能完全適合分析和報告需求,而MySQL可能存儲計費事務。幸運的是,在本教程的幫助下,您將能夠選擇合適的工具來完成這項工作。

在很多方面,可以公平地說,MongoDB是為Web構建的:包含JSON,非常短的學習曲線,快速開發的基礎,每個發行版都增加了新功能。MySQL是經過戰鬥測試,保守和舊時尚的,但隨著關係數據商店嘗試適應現代應用程序需求,事情正在發生非常快的變化。

5.15。MySQL或MongoDB?

已經有很多關於MySQL和MongoDB的文章。當MongoDB比MySQL更受歡迎時,使用一組建議來完成討論會很好,反之亦然。

首先,如果你的數據對你的業務至關重要,MySQL很可能是一個更安全的選擇:ACID屬性是有原因的。但是每個應用程序都不同。內容管理系統,日誌管理,分析,論壇和博客,事件存儲,產品目錄,庫存管理,這些類型的應用程序都可能受益於MongoDB作為數據存儲。

無模式數據模型是快速開發的推動因素:只需引入新屬性,無需執行模式演變和數據遷移。可以說,但MongoDB處理文檔和運行查詢的風格更適合開發人員(而且,它不需要學習任何語言,如SQL)。與MySQL Cluster配置(和管理)相比,配置MongoDB的副本集和分片集群非常簡單快捷。

現代架構模式正在推動將應用程序的讀寫路徑分開(例如命令和查詢責任分離或僅CQRS)。因此,應用程序可以通過MySQL提供寫入路徑的方式進行設計,但MongoDB可能是讀取路徑的數據存儲器,其中數據片段被組合成有意義的文檔。

5.16。MySQL和MongoDB:現在

值得一提的是,Twitter和Facebook兩家公司成功運行了部分最大的MySQL部署。他們愉快地分享他們雖然眾多的博客文章的經驗:MySQL的在Twitter的,再看一下MySQL的在Twitter和孵化Mysos,Twitter將儲存250億如何鳴叫一個天使用MySQL,WebScaleSQL:將合作建立在MySQL的上游,等等。

從另一方面來說,隨著越來越多的公司在越來越大規模部署它,MongoDB的採用日益增多。例如,eBay分享了我們如何構建eBay的第一個Node.js應用程序,而Craigslist 在Craigslist:1年後跟進了MongoDB。毫無疑問,我們將在未來看到更廣泛的採用。

6.結論

在這個簡短的教程中,我們嘗試著看看兩個非常流行的數據存儲,由MySQL代表的傳統關係數據庫和由MongoDB代表的文檔數據存儲。我們簡要介紹了其中的每個重要功能和數據保證,試圖評估應用程序的可伸縮性和可用性如何受到影響。我們省略了很多低級固有的細節,因為MySQL和MongoDB都只值幾本書。相反,我們做了一個高層次的概述,挑選了最有趣和最重要的領域。


分享到:


相關文章: