在前一篇文章中我們主要的討論了SQL與NoSQL數據庫之間的主要的差別。接下來,我們將會利用上一篇中的知識來確定在特定的場景中如何確定比較好的選擇。
首先我們先來總結一下:
SQL數據庫:
-
-
在使用表之前需要先定義標的模式
-
鼓勵使用規范化來減少數據的冗余
-
支持使用JOIN操作,使用一條SQL語句從多張表中取出相關的數據
-
需要滿足數據完整性約束規則
-
使用事務來保證數據的一致性
-
能夠大規模的使用
-
使用強大的SQL語言進行查詢操作
-
提供大量的支持,專業技能和輔助工具
-
使用類JSON格式的文檔來存儲鍵值對信息
-
存儲數據不需要特定的模式
-
使用非規范化的標准存儲信息,以保證一個文檔中包含一個條目的所有信息
-
不需要使用JOIN操作
-
允許數據不用通過驗證就可以存儲到任意的位置
-
保證更新的單個文檔,而不是多個文檔
-
提供卓越的性能和可擴展性
-
使用JSON數據對象進行查詢
-
是一種新型的技術
SQL數據庫適合那些需求確定和對數據完整性要去嚴格的項目。NoSQL數據庫適用於那些對速度和可擴展性比較看重的那些不相關的,不確定和不斷發展的需求。簡單來說就是:
-
SQL是精確的。它最適合於具有精確標准的定義明確的項目。典型的使用場景是在線商店和銀行系統。
-
NoSQL是多變的。它最適合於具有不確定需求的數據。典型的使用場景是社交網絡,客戶管理和網絡分析系統。
很少有項目能夠很好的適用於一種數據庫。如果你對數據的需求比較小或是非標准化的數據任何一種數據庫都是可以的。你比我更了解你的項目,我不建議你將SQL上的數據移植到NoSQL上反之亦然,除非它能夠提供非常可觀的收益。當然選擇權在於你自己。在項目的一開始就要考慮好使用它們的利弊,這樣才不會導致選擇錯誤。
場景一:通訊記錄
我們來重新的定義操作並基於SQL實現通訊錄系統。我們初始簡單的定義contact
表擁有如下幾個字段;
-
id
-
title
-
firstname
-
lastname
-
gender
-
telephone
-
email
-
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來替代SQL
我們的聯系人關注的是人這個實體。然而關於人的信息是不可預測的並且在不同的階段的需求也會不一樣。如果我們使用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)
建議:去嘗試了解更多新的技術。這樣我們就可以非常有理由的選擇一種數據庫進行開發。祝你好運!