在前一篇文章中咱們主要的討論了SQL與NoSQL數據庫之間的主要的差異。接下來,咱們將會利用上一篇中的知識來肯定在特定的場景中如何肯定比較好的選擇。html
首先咱們先來總結一下:數據庫
SQL數據庫:網絡
ide
在使用表以前須要先定義標的模式工具
鼓勵使用規範化來減小數據的冗餘性能
支持使用JOIN操做,使用一條SQL語句從多張表中取出相關的數據this
須要知足數據完整性約束規則spa
使用事務來保證數據的一致性.net
可以大規模的使用設計
使用強大的SQL語言進行查詢操做
提供大量的支持,專業技能和輔助工具
使用類JSON格式的文檔來存儲鍵值對信息
存儲數據不須要特定的模式
使用非規範化的標準存儲信息,以保證一個文檔中包含一個條目的全部信息
不須要使用JOIN操做
容許數據不用經過驗證就能夠存儲到任意的位置
保證更新的單個文檔,而不是多個文檔
提供卓越的性能和可擴展性
使用JSON數據對象進行查詢
是一種新型的技術
SQL數據庫適合那些需求肯定和對數據完整性要去嚴格的項目。NoSQL數據庫適用於那些對速度和可擴展性比較看重的那些不相關的,不肯定和不斷髮展的需求。簡單來講就是:
SQL是精確的。它最適合於具備精確標準的定義明確的項目。典型的使用場景是在線商店和銀行系統。
NoSQL是多變的。它最適合於具備不肯定需求的數據。典型的使用場景是社交網絡,客戶管理和網絡分析系統。
不多有項目可以很好的適用於一種數據庫。若是你對數據的需求比較小或是非標準化的數據任何一種數據庫都是能夠的。你比我更瞭解你的項目,我不建議你將SQL上的數據移植到NoSQL上反之亦然,除非它可以提供很是可觀的收益。固然選擇權在於你本身。在項目的一開始就要考慮好使用它們的利弊,這樣纔不會致使選擇錯誤。
咱們來從新的定義操做並基於SQL實現通信錄系統。咱們初始簡單的定義contact
表擁有以下幾個字段;
id
title
firstname
lastname
gender
telephone
address1
address2
address3
city
region
zipcode
country
問題一:不多有人只擁有一個手機號。或許咱們能夠再添加三個字段:固定電話,移動電話和工做電話,可是不管咱們給一個聯繫人分配了多少個字段總會有人須要更多。咱們須要建立一個單獨的telephone
表,這樣就能夠給一個聯繫人存多個號碼了。這樣也就規範化了咱們的數據— 咱們不須要一個沒有電話的聯繫人:
contact_id
name (說明字段:固定,工做,私人等.)
number
問題二:對於聯繫人郵箱咱們也會遇到上述問題,所以咱們也須要建立一個email
的表:
contact_id
name (說明字段:固定,工做,私人等.)
address
問題三:咱們在填寫聯繫人信息是咱們並不但願填寫他的地理位置,或者咱們想記錄他工做、生活、旅遊的地方等。所以咱們須要一個address
表:
contact_id
name (text such as home, office, etc.)
address1
address2
address3
city
region
zipcode
country
咱們原先設計的contact
表就精簡爲:
id
title
firstname
lastname
gender
好了,咱們已經設計了一個規範化的數據庫,能夠用來存儲任何一個聯繫人的電話號碼,郵箱地址和住址了。可是......
模式是固定不變的
咱們並無考慮到聯繫人的生日,公司或者職位。無論咱們添加多少個字段,咱們會獲得更多的需求:備註,週年記念日,關係,社交帳號,喜歡巧克力的種類等等。預測每個需求對於咱們來講是很是困難的,所以咱們須要建立一張表其中存儲的形式是鍵值對來應對不斷增長的需求。
數據是碎片化的
對於開發人員和系統管理員來講不斷地檢查數據庫是比較麻煩的。程序的邏輯會變得更復雜效率更慢,由於使用一條select
語句來JOIN
多個表來取出一個聯繫人的所有信息不太實際。(固然這也是能夠實現的,可是當一個聯繫人中國包含電話號碼,郵件地址和住址信息時:若是一我的有3個電話號碼,五個郵箱和兩個住址,那麼SQL查詢會產生30個結果,也就是說說這樣的效率會很慢。)
最後,全文搜索是很是困難的。若是一我的要查詢一個字符型:favorite,咱們須要依次查詢上述的四張表判斷是不是一個聯繫人的姓名,電話,郵件或者地址依據這些把結果進行排序。若是你使用過WordPress
的搜索,你就會發現是都麼的煩人了!
咱們的聯繫人關注的是人這個實體。然而關於人的信息是不可預測的而且在不一樣的階段的需求也會不同。若是咱們使用NoSQL數據庫會比較方便,NoSQL將一我的的信息存儲爲一個文檔並放入contacts
的集合中:
{ name: [ "Billy", "Bob", "Jones" ], company: "Fake Goods Corp", jobtitle: "Vice President of Data Management", telephone: { home: "0123456789", mobile: "9876543210", work: "2244668800" }, email: { personal: "bob@myhomeemail.net", work: "bob@myworkemail.com" }, address: { home: { line1: "10 Non-Existent Street", city: "Nowhere", country: "Australia" } }, birthdate: ISODate("1980-01-01T00:00:00.000Z"), twitter: '@bobsfakeaccount', note: "Don't trust this guy", weight: "200lb", photo: "52e86ad749e0b817d25c8892.jpg" }
在這個示例中,咱們沒有存儲這我的的性別和職銜,而且能夠添加一些別的聯繫人沒用的信息。在NoSQL中這樣的存儲是合法的,而且咱們能夠按照各人的意願來添加和刪除一個字段。
由於一個聯繫人存儲在一個文檔中,所以咱們可使用一個查詢語句取出一我的的全部信息。對於全文搜索,在MongoDB中咱們能夠在contact
的字段中定義一個索引:
db.contact.createIndex({ "$**": "text" });
而後咱們就可使用以下的語句進行全文搜索:
db.contact.find({ $text: { $search: "something" } });
一個典型的社交網絡使用的聯繫人的信息是類似,可是也會增長一些新的功能例如:社交網絡,狀態更新,私信和點贊。這些功能會根據用戶的需求進行添加或者刪除,預測用戶的需求對開發人員來講是很是困難的。
另外:
大多數的更新都有一個原始的出發點:用戶。可是,對於開發人員來講一次性的把全部的回饋都進行更新是不可能的。
無論用戶怎麼想,一個失敗的版本並可能形成太大的經濟損失。一個應用的接口設計和功能表現是比數據的完整性的優先級要高。
所以,NoSQL是一個不錯的選擇。數據庫容許咱們存儲不一樣類型的數據以便於咱們快速的開發出新的功能。例如,由於全部的數據狀態的更新均可以在status
的集合中的一個文檔中進行:
{ user_id: ObjectID("65f82bda42e7b8c76f5c1969"), update: [ { date: ISODate("2015-09-18T10:02:47.620Z"), text: "feeling more positive today" }, { date: ISODate("2015-09-17T13:14:20.789Z"), text: "spending far too much time here" } { date: ISODate("2015-09-17T12:33:02.132Z"), text: "considering my life choices" } ] }
儘管對於這個文檔來講數據會變得多一些,可是咱們能夠僅僅取出文檔的一個子集,例如:最新的狀態等。對於每個用戶來講歷史記錄也會很容易搜索的到。
如今,咱們來分析一下一個倉庫的管理系統。咱們須要記錄以下的信息:
貨物入庫的信息和存放的位置信息
貨物在倉庫中的移動,例如:爲相同的貨物分配相鄰的位置存放
貨物的擺放順序以及配送貨物以後的一系列問題。
數據需求:
保存貨物的基本信息例如:尺寸、大小、顏色等,這些不相關的數據咱們要可以用到任何的貨物上。咱們不可能去考慮一些貨物個性化的信息例如:筆記本處理器的速度或者是一部手機電池的壽命。
咱們要儘量的避免錯誤的發生。咱們不能讓貨物憑空消失或者將貨物存放到已經存放貨物的位置上去。
以更加簡單的方式操做。咱們記錄將一件貨物從一個位置移動到另外一個位置或者從A移動到B的操做是相同的。
所以,咱們須要考慮對數據的完整性和對於事務的支持。目前來講也就是SQL可以很好地知足咱們的需求。
我但願上述的案例可以對你有必定的幫助,可是每個實際的項目都是不一樣的,對一無二的你須要本身去作決定選擇一種適合的。(儘管,對於咱們開發人員來講咱們不太願意去改變咱們現有的選擇,不管新的技術有多好!O(∩_∩)O)
建議:去嘗試瞭解更多新的技術。這樣咱們就能夠很是有理由的選擇一種數據庫進行開發。祝你好運!