聲明:本文譯自SQL vs NoSQL The Differences,如需轉載請註明出處。前端
SQL(結構化查詢語言)數據庫做爲一個主要的數據存儲機制已經超過40個年頭了。隨着web應用和像MySQL、PostgreSQL和SQLite這些開源項的興起,SQL使用量大大增長。web
NoSQL數據庫在20世紀60年代就已經出現了,但最近由於MongoDB、CouchDB,Redis和Apache Cassandra等才受到普遍的關注。sql
你會發現不少教程都會解釋如何根據你的興趣選擇去使用SQL仍是NoSQL,可是不多討論爲何應該去選擇它。我但願可以填補這一空白。在這篇文章中,咱們將介紹基本的差別。在稍後的後續的文章中,咱們將查看一些典型的場景,並肯定最佳的選擇。數據庫
大多數的例子都適用於目前流行的MySQL SQL和MongoDB NoSQL數據庫系統。其餘SQL/NOSQL數據庫都是相似的,但會有細微的差異和語法特徵。安全
在咱們開始以前,先糾正一些所謂的神話…服務器
神話1:NoSQL將取代SQL架構
這麼說就比如說船將被車取代,由於它是新的技術。SQL和NoSQL作的是相同的事:數據存儲。它們採起的方法不一樣,這可能回幫組或阻礙你的項目。儘管感受技術更新,並常常在最近上頭條,NoSQL不是SQL的替代品——而是一種選擇。框架
神話2:NoSQL比SQL更好或更壞nosql
一些項目更適合使用SQL數據庫,一些更適合NoSQL,而一些能夠二者交替使用。這邊文章不會是SitePoint Smackdown,由於你不能在全部方面都應用相同的普遍性假設。性能
神話3:SQL和NoSQL天壤之別
這不必定是個事實。一些SQL數據庫採用NoSQL的特色,反之亦然。選擇可能會變得愈來愈模糊,NewSQL混合數據庫可能會在未來提供一些有趣的選擇。
神話4:語言/框架決定了使用什麼樣的數據庫
咱們已經習慣了技術堆,好比——
有實踐的、歷史的和商業的緣由來解釋這些stack的發展——但不能認爲它們就是規則。你能夠在你的PHP或.NET項目中使用MongoDB NoSQL數據庫。你能夠在Node.js中鏈接MySQL或者SQL服務器。你可能沒有找到不少教程和資源,可是是你的需求決定數據庫的類型——而不是所謂的語言。
(有句話是這麼說的,不要讓生活有目地爲難本身!選擇一個不尋常的技術組合或者SQL和NoSQL組合是可行的,但困難的是找到支持和聘請有經驗的開發者)
有了這樣的想法,咱們來看看主要的差別。
SQL數據庫提供相關數據表的存儲。例如,若是你有一個網上書店,圖書的信息將會被添加到一個book的表中:
每一行是一個不一樣的記錄。設計是剛性的;你不能使用同一個表來存儲不一樣的信息,或者在一個數字格式輸入字符。
NoSQL數據庫存儲JSON格式的字段值對文檔,好比:
{ ISBN: 9780992461225, title: "JavaScript: Novice to Ninja", author: "Darren Jones", format: "ebook", price: 29.00 }
類似的文檔能夠存儲於一個集合裏,這相似於一個SQL表。然而你能夠存儲任何數據在任何文檔裏;而NoSQL數據庫永遠不會抱怨,例如:
{ ISBN: 9780992461225, title: "JavaScript: Novice to Ninja", author: "Darren Jones", format: "ebook", price: 29.00 }
SQL表建立一個嚴格的數據模板,所以很難犯錯誤。NoSQL更加的靈活和寬容,但可以存儲任何數據可能會致使一致性的問題。
在一個SQL數據庫中,除非你在指定模式中定義了表格和字段格式,否則不可能添加數據。該模式還能夠包含其餘的信息,例如——
主鍵——惟一的標識符,如ISBN,適用於單個記錄。
索引——一般被查詢的字段,用來幫助快熟搜索。
關係——數據字段之間的邏輯鏈接
功能——如觸發器和存儲過程
你的數據模式必須在任何商業邏輯能夠被開發去處理數據前被設計出來並實現。完成後能夠行進一些更新,但不能完成大的改變。
在一個NoSQL數據庫,數據能夠隨時隨地被添加。沒有必要去制定一個文檔設計,甚至集合前端。例如在MongoDB,下面的語句將在新的book集合建立一個新的文檔,若是這個文檔以前沒有被建立過:
db.book.insert( ISBN: 9780994182654, title: "Jump Start Git", author: "Shaumik Daityari", format: "ebook", price: 29.00 );
(MongoDB會給每一個集合內的文檔自動添加惟一的_id值。你可能任然想要定義索引,若是須要的話能夠稍後進行。)
若是一個項目初始數據要求很難去肯定,那麼NoSQL數據庫可能更加的適合。有句話說,不要爲懶散而製造困難:忽略了在項目中設計適合的數據庫的重要性將會在以後致使不少的麻煩。
假設咱們要向書店數據庫中添加出版商信息。一個單一的出版商能夠提供多個標題,在一個SQL數據庫裏,咱們建立一個新的publisher表:
咱們接下來能夠增長publisher_id到book表,這個表是publisher.id引用。
這最大限度的減小數據的冗餘;咱們不用重複每本書的出版商信息——僅僅只用索引。這種技巧能夠稱做規範化,並有實際的好處。咱們只用更新單一的出版商而不用改變整個book數據。
在NoSQL中,咱們也可使用規範化技巧。在book集中的文檔——
{ ISBN: 9780992461225, title: "JavaScript: Novice to Ninja", author: "Darren Jones", format: "ebook", price: 29.00, publisher_id: "SP001" }
——在一個出版商集合中引用一個文檔:
{ id: "SP001" name: "SitePoint", country: "Australia", email: "feedback@sitepoint.com" }
然而,這並不老是可行的,緣由在下面很明顯。咱們可能選擇反規範化咱們的文檔,重複每本書的出版商信息:
{ ISBN: 9780992461225, title: "JavaScript: Novice to Ninja", author: "Darren Jones", format: "ebook", price: 29.00, publisher: { name: "SitePoint", country: "Australia", email: "feedback@sitepoint.com" } }
這能夠加快查詢的速度,但在多個記錄中更新出版商信息將會顯著變慢。
SQL查詢提供了一個強大的JOIN條款。咱們可使用單個SQL語句獲取不一樣表中的相關數據。例如:
SELECT book.title, book.author, publisher.name
FROM book
LEFT JOIN book.publisher_id ON publisher.id;
這將返回全部的書名、做者和相關出版商名稱。
NoSQL沒有等效的JOIN,有SQL的經驗的可能會驚訝. 若是咱們使用上述的規範化集合,咱們將須要獲取全部的book文檔,檢索全部的相關publisher文檔,並手動在程序邏輯中鏈接二者。這就是反規範化經常是必不可少的一個緣由。
大多數SQL數據庫容許你使用外鍵約束去強制性數據完整性(除非你仍在使用舊的,在MySQL已不存在的MyISAM存儲引擎)。咱們的書店能夠——
模式強制數據庫遵循這些規則。開發者或用戶則不能增長、編輯或者移除可能引發無效數據或孤立的數據
相同數據完整性選項在NoSQL數據庫中不可用;你能夠存儲全部你想存儲的東西。理想狀況下,單一文檔將成爲項目全部信息的惟一來源。
在SQL數據庫中,兩個或多個更新能夠在同一個事務中執行——一個all-or-nothing的封裝保證成功或失敗。例如,假設咱們的書店包含了order和stock表。當一本書被訂購時,咱們在order表添加一條記錄並減小stock表中的庫存數。若是咱們分別地執行這兩個更新,一個可能成功另一個會失敗——所以咱們的數據會不一樣步。在一個事務中放置相同更新能夠保證同時成功或失敗。
在NoSQL數據庫中,單個文檔的修改是微小的。換句話說。若是你正在文檔中更新三個值,要不三個值都是成功的,要不三個值都保持不變。然而,卻沒有相等的事務去更新不一樣的文檔。有相似的選項,可是,在寫這些的時候,必須在你的代碼中手動處理。
建立、讀取更新和刪除數據是上全部數據庫系統的基礎。本質上——
簡單的比較:
這也許是最有爭議的比較,NoSQL常常被認爲比SQL更快。這並不奇怪;NoSQL更加簡單的反規範化存儲容許你使用單個請求去在全部信息中查詢一個特定的項目。不須要使用相關的JSON或複雜的SQL查詢。
也就是說,你的項目設計和數據要求將產生最大的影響。一個良好設計的SQL數據庫必然會比一個設計不好的NoSQL表現要好,反之亦然。
隨着你的數據的增加,你可能會發如今多個服務器以前分配負載是很必要的。這對於SQL爲基礎的系統可能很棘手。如何分配相關的數據呢?聚類多是最簡單的選擇;多個服務器訪問相同的中央存儲——但即便這樣也會存在挑戰。
NoSQL的簡單數據模型可讓這個過程容易不少,許多一開始就創建了縮放功能。這是一個概論性的,因此若是碰到這種狀況請去諮詢專家意見。
最後,咱們來考慮安全和系統的問題。最有名的NoSQL數據庫才存在了幾年;他們比更成熟的SQL產品更易出現問題。許多的問題已經被曝光,但大部分仍是歸結爲一個問題:知識。
開發人員和系統管理員對於新的數據庫系統有較少的經驗,因此錯誤經常發生。選擇NoSQL是由於它感受會更快,或由於你想去避免架構設計而致使以後的問題。
SQL和NoSQL數據庫用不一樣的方式作一樣的事情。從一個切換到另外一個是可能的,可是一點計劃能夠節約不少的時間和金錢。
更適合SQL的項目:
可預先肯定的邏輯關係離散數據的要求
數據完整性是必不可少的
有良好開發經驗和支持的標準基礎技術
更適合NoSQL的項目:
不相關的、不肯定或不斷變化的數據要求
更加簡單寬鬆的項目對象,能夠當即編碼
速度和擴展性是必要的
在這個書店例子的背景下,SQL數據庫是最實用的選項——特別是當咱們引進電商設施,須要強大的事務支持。
因爲咱們雲巴是作跨設備平臺的消息服務的,對數據存取的速度和擴展要求很是高,NoSQl對咱們來講是最合適的。