SQL VS NoSQL 如何選擇數(shù)據(jù)庫

在前一篇文章中我們主要的討論了SQL與NoSQL數(shù)據(jù)庫之間的主要的差別腐宋。接下來紊服,我們將會利用上一篇中的知識來確定在特定的場景中如何確定比較好的選擇。

首先我們先來總結(jié)一下:

SQL數(shù)據(jù)庫:

  • 使用表存儲相關(guān)的數(shù)據(jù)
  • 在使用表之前需要先定義標(biāo)的模式
  • 鼓勵使用規(guī)范化來減少數(shù)據(jù)的冗余
  • 支持使用JION操作胸竞,使用一條SQL語句從多張表中取出相關(guān)的數(shù)據(jù)
  • 需要滿足數(shù)據(jù)完整性約束規(guī)則
  • 使用事務(wù)來保證數(shù)據(jù)的一致性
  • 能夠大規(guī)模的使用
  • 使用強(qiáng)大的SQL語言進(jìn)行查詢操作
  • 提供大量的支持欺嗤,專業(yè)技能和輔助工具

NoSQL數(shù)據(jù)庫:

  • 使用類JOSN格式的文檔來存儲鍵值對信息
  • 存儲數(shù)據(jù)不需要特定的模式
  • 使用非規(guī)范化的標(biāo)準(zhǔn)存儲信息,以保證一個文檔中包含一個條目的所有信息
  • 不需要使用JION操作
  • 允許數(shù)據(jù)不用通過驗(yàn)證就可以存儲到任意的位置
  • 保證更新的單個文檔卫枝,而不是多個文檔
  • 提供卓越的性能和可擴(kuò)展性
  • 使用JOSN數(shù)據(jù)對象進(jìn)行查詢
  • 是一種新型的技術(shù)

SQL數(shù)據(jù)庫適合那些需求確定和對數(shù)據(jù)完整性要去嚴(yán)格的項(xiàng)目煎饼。NoSQL數(shù)據(jù)庫適用于那些對速度和可擴(kuò)展性比較看重的那些不相關(guān)的,不確定和不斷發(fā)展的需求校赤。簡單來說就是:

  • SQL是精確的吆玖。它最適合于具有精確標(biāo)準(zhǔn)的定義明確的項(xiàng)目。典型的使用場景是在線商店和銀行系統(tǒng)马篮。
  • NoSQL是多變的沾乘。它最適合于具有不確定需求的數(shù)據(jù)。典型的使用場景是社交網(wǎng)絡(luò)浑测,客戶管理和網(wǎng)絡(luò)分析系統(tǒng)翅阵。

很少有項(xiàng)目能夠很好的適用于一種數(shù)據(jù)庫。如果你對數(shù)據(jù)的需求比較小或是非標(biāo)準(zhǔn)化的數(shù)據(jù)任何一種數(shù)據(jù)庫都是可以的。你比我更了解你的項(xiàng)目掷匠,我不建議你將SQL上的數(shù)據(jù)移植到NoSQL上反之亦然读慎,除非它能夠提供非常可觀的收益槐雾。當(dāng)然選擇權(quán)在于你自己。在項(xiàng)目的一開始就要考慮好使用它們的利弊幅狮,這樣才不會導(dǎo)致選擇錯誤募强。

場景一:通訊記錄

我們來重新的定義操作并基于SQL實(shí)現(xiàn)通訊錄系統(tǒng)。我們初始簡單的定義contact表擁有如下幾個字段;

  • id
  • title
  • firstname
  • lastname
  • gender
  • telephone
  • email
  • address1
  • address2
  • address3
  • city
  • region
  • zipcode
  • country

問題一:很少有人只擁有一個手機(jī)號崇摄∏嬷担或許我們可以再添加三個字段:固定電話,移動電話和工作電話逐抑,但是無論我們給一個聯(lián)系人分配了多少個字段總會有人需要更多鸠儿。我們需要創(chuàng)建一個單獨(dú)的telephone表,這樣就可以給一個聯(lián)系人存多個號碼了厕氨。這樣也就規(guī)范化了我們的數(shù)據(jù)— 我們不需要一個沒有電話的聯(lián)系人:

  • contact_id
  • name (說明字段:固定进每,工作,私人等.)
  • number

問題二:對于聯(lián)系人郵箱我們也會遇到上述問題命斧,因此我們也需要創(chuàng)建一個email的表:

  • contact_id
  • name (說明字段:固定田晚,工作,私人等.)
  • address

問題三:我們在填寫聯(lián)系人信息是我們并不希望填寫他的地理位置国葬,或者我們想記錄他工作贤徒、生活、旅游的地方等汇四。因此我們需要一個address表:

  • contact_id
  • name (text such as home, office, etc.)
  • address1
  • address2
  • address3
  • city
  • region
  • zipcode
  • country

我們原先設(shè)計(jì)的contact表就精簡為:

  • id
  • title
  • firstname
  • lastname
  • gender

好了接奈,我們已經(jīng)設(shè)計(jì)了一個規(guī)范化的數(shù)據(jù)庫,可以用來存儲任何一個聯(lián)系人的電話號碼通孽,郵箱地址和住址了序宦。但是......

模式是固定不變的

我們并沒有考慮到聯(lián)系人的生日,公司或者職位利虫。不管我們添加多少個字段挨厚,我們會得到更多的需求:備注,周年紀(jì)念日糠惫,關(guān)系疫剃,社交賬號,喜歡巧克力的種類等等硼讽。預(yù)測每一個需求對于我們來說是非常困難的巢价,因此我們需要創(chuàng)建一張表其中存儲的形式是鍵值對來應(yīng)對不斷增加的需求。

數(shù)據(jù)是碎片化的

對于開發(fā)人員和系統(tǒng)管理員來說不斷地檢查數(shù)據(jù)庫是比較麻煩的。程序的邏輯會變得更復(fù)雜效率更慢壤躲,因?yàn)槭褂靡粭lselect語句來JOIN多個表來取出一個聯(lián)系人的全部信息不太實(shí)際城菊。(當(dāng)然這也是可以實(shí)現(xiàn)的,但是當(dāng)一個聯(lián)系人中國包含電話號碼碉克,郵件地址和住址信息時:如果一個人有3個電話號碼凌唬,五個郵箱和兩個住址,那么SQL查詢會產(chǎn)生30個結(jié)果漏麦,也就是說說這樣的效率會很慢客税。)

最后,全文搜索是非常困難的撕贞。如果一個人要查詢一個字符型:favorite更耻,我們需要依次查詢上述的四張表判斷是否是一個聯(lián)系人的姓名,電話捏膨,郵件或者地址依據(jù)這些把結(jié)果進(jìn)行排序秧均。如果你使用過WordPress的搜索,你就會發(fā)現(xiàn)是都么的煩人了号涯!

使用NoSQL來替代SQL

我們的聯(lián)系人關(guān)注的是人這個實(shí)體目胡。然而關(guān)于人的信息是不可預(yù)測的并且在不同的階段的需求也會不一樣。如果我們使用NoSQL數(shù)據(jù)庫會比較方便链快,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"
}

在這個示例中讶隐,我們沒有存儲這個人的性別和職銜,并且可以添加一些別的聯(lián)系人沒用的信息久又。在NoSQL中這樣的存儲是合法的巫延,并且我們可以按照各人的意愿來添加和刪除一個字段。

因?yàn)橐粋€聯(lián)系人存儲在一個文檔中地消,因此我們可以使用一個查詢語句取出一個人的所有信息炉峰。對于全文搜索,在MongoDB中我們可以在contact的字段中定義一個索引:

db.contact.createIndex({ "$**": "text" });

然后我們就可以使用如下的語句進(jìn)行全文搜索:

db.contact.find({
  $text: { $search: "something" }
});

場景二:社交網(wǎng)絡(luò)

一個典型的社交網(wǎng)絡(luò)使用的聯(lián)系人的信息是相似脉执,但是也會增加一些新的功能例如:社交網(wǎng)絡(luò)疼阔,狀態(tài)更新,私信和點(diǎn)贊半夷。這些功能會根據(jù)用戶的需求進(jìn)行添加或者刪除婆廊,預(yù)測用戶的需求對開發(fā)人員來說是非常困難的。

另外:

  • 大多數(shù)的更新都有一個原始的出發(fā)點(diǎn):用戶巫橄。但是淘邻,對于開發(fā)人員來說一次性的把所有的回饋都進(jìn)行更新是不可能的。
  • 不管用戶怎么想湘换,一個失敗的版本并可能造成太大的經(jīng)濟(jì)損失宾舅。一個應(yīng)用的接口設(shè)計(jì)和功能表現(xiàn)是比數(shù)據(jù)的完整性的優(yōu)先級要高统阿。

因此,NoSQL是一個不錯的選擇筹我。數(shù)據(jù)庫允許我們存儲不同類型的數(shù)據(jù)以便于我們快速的開發(fā)出新的功能扶平。例如,因?yàn)樗械臄?shù)據(jù)狀態(tài)的更新都可以在status的集合中的一個文檔中進(jìn)行:

{
  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"
    }
  ]
}

盡管對于這個文檔來說數(shù)據(jù)會變得多一些蔬蕊,但是我們可以僅僅取出文檔的一個子集结澄,例如:最新的狀態(tài)等。對于每一個用戶來說歷史記錄也會很容易搜索的到岸夯。

場景三:倉庫管理系統(tǒng)

現(xiàn)在概而,我們來分析一下一個倉庫的管理系統(tǒng)。我們需要記錄如下的信息:

  • 貨物入庫的信息和存放的位置信息
  • 貨物在倉庫中的移動囱修,例如:為相同的貨物分配相鄰的位置存放
  • 貨物的擺放順序以及配送貨物之后的一系列問題。

數(shù)據(jù)需求:

  1. 保存貨物的基本信息例如:尺寸王悍、大小破镰、顏色等,這些不相關(guān)的數(shù)據(jù)我們要能夠用到任何的貨物上压储。我們不可能去考慮一些貨物個性化的信息例如:筆記本處理器的速度或者是一部手機(jī)電池的壽命鲜漩。
  2. 我們要盡可能的避免錯誤的發(fā)生。我們不能讓貨物憑空消失或者將貨物存放到已經(jīng)存放貨物的位置上去集惋。
  3. 以更加簡單的方式操作孕似。我們記錄將一件貨物從一個位置移動到另一個位置或者從A移動到B的操作是相同的。

因此刮刑,我們需要考慮對數(shù)據(jù)的完整性和對于事務(wù)的支持喉祭。目前來說也就是SQL能夠很好地滿足我們的需求。

總結(jié)

我希望上述的案例能夠?qū)δ阌幸欢ǖ膸椭拙睿敲恳粋€實(shí)際的項(xiàng)目都是不同的泛烙,對一無二的你需要自己去做決定選擇一種適合的。(盡管翘紊,對于我們開發(fā)人員來說我們不太愿意去改變我們現(xiàn)有的選擇蔽氨,無論新的技術(shù)有多好!O(∩_∩)O)

建議:去嘗試了解更多新的技術(shù)帆疟。這樣我們就可以非常有理由的選擇一種數(shù)據(jù)庫進(jìn)行開發(fā)鹉究。祝你好運(yùn)!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末踪宠,一起剝皮案震驚了整個濱河市自赔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌柳琢,老刑警劉巖匿级,帶你破解...
    沈念sama閱讀 216,843評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蟋滴,死亡現(xiàn)場離奇詭異,居然都是意外死亡痘绎,警方通過查閱死者的電腦和手機(jī)津函,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來孤页,“玉大人尔苦,你說我怎么就攤上這事⌒惺” “怎么了允坚?”我有些...
    開封第一講書人閱讀 163,187評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蛾号。 經(jīng)常有香客問我稠项,道長,這世上最難降的妖魔是什么鲜结? 我笑而不...
    開封第一講書人閱讀 58,264評論 1 292
  • 正文 為了忘掉前任展运,我火速辦了婚禮,結(jié)果婚禮上精刷,老公的妹妹穿的比我還像新娘拗胜。我一直安慰自己,他們只是感情好怒允,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,289評論 6 390
  • 文/花漫 我一把揭開白布埂软。 她就那樣靜靜地躺著,像睡著了一般纫事。 火紅的嫁衣襯著肌膚如雪勘畔。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,231評論 1 299
  • 那天丽惶,我揣著相機(jī)與錄音咖杂,去河邊找鬼。 笑死蚊夫,一個胖子當(dāng)著我的面吹牛诉字,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播知纷,決...
    沈念sama閱讀 40,116評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼壤圃,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了琅轧?” 一聲冷哼從身側(cè)響起伍绳,我...
    開封第一講書人閱讀 38,945評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎乍桂,沒想到半個月后冲杀,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體效床,經(jīng)...
    沈念sama閱讀 45,367評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,581評論 2 333
  • 正文 我和宋清朗相戀三年权谁,在試婚紗的時候發(fā)現(xiàn)自己被綠了剩檀。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,754評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡旺芽,死狀恐怖沪猴,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情采章,我是刑警寧澤运嗜,帶...
    沈念sama閱讀 35,458評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站悯舟,受9級特大地震影響担租,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜抵怎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,068評論 3 327
  • 文/蒙蒙 一奋救、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧便贵,春花似錦、人聲如沸冗荸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蚌本。三九已至盔粹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間程癌,已是汗流浹背舷嗡。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留嵌莉,地道東北人进萄。 一個月前我還...
    沈念sama閱讀 47,797評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像锐峭,于是被迫代替她去往敵國和親中鼠。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,654評論 2 354

推薦閱讀更多精彩內(nèi)容