關係型資料庫與NoSQL資料庫場景說明
一個程式設計師很有必要熟悉或者精通一種資料庫,MySQL無疑是首選。為什麼使用MySQL呢,因為它是開源的,同時具備輕量、簡單、穩定和高效能等特點,尤其是其學習成本相對其他資料庫,比如Oracle和Sybase更簡單,入門更低。MySQL的應用範圍從中小型Web網站到大型的企業級應用隨處都可見它的身影。
關係型資料庫
關係型資料庫把所有的資料都通過行和列的二元表現形式表示出來。它的優勢:
-
保持資料的一致性(事務處理)
-
由於以標準化為前提,資料更新的開銷很小(相同的欄位基本上都只有一處)
-
可以進行Join等複雜查詢
-
能夠保持資料的一致性是關係型資料庫的最大優勢
關係型資料庫的效能非常高,但是它畢竟是一個通用型的資料庫,並不能完全適應所有的用途,具體來說它並不擅長以下處理:
-
大量資料的寫入處理。
-
為有資料更新的表做索引或表結構(schema)變更
-
欄位不固定時應用
-
對簡單查詢需要快速返回結果的處理
大量資料的寫入處理:
在資料讀入方面,由複製產生的主從模式(資料的寫入由主資料庫負責,資料的讀入由從資料庫負責),可以比較簡單地通過增加從資料庫來實現規模化。但是,在資料的寫入方面卻完全沒有簡單的方法來解決規模化問題。例如,要想將資料的寫入規模化,可以考慮把主資料庫從一套增加到兩臺,作為互相關聯複製的二元主資料庫來使用。確實這樣似乎可以把每臺主資料庫的負荷減少一半,但是更新處理會產生衝突(同樣的資料在兩臺伺服器同時更新成其他值),可能會造成資料的不一致。為了避免這樣的問題,就需要把每個表的請求分別分配給合適的主資料庫來處理,這就不那麼簡單了。
另外也可以考慮把資料庫分割開來,分別放在不同的資料庫伺服器上,比如將這個表放在這個資料庫伺服器上,那個表放在那個資料庫伺服器上,資料庫分割可以減少每臺數據庫伺服器上的資料量,以便減少硬碟I/O處理,實現記憶體上的高速處理,效果非常顯著。但是,由於分別儲存在不同伺服器上的表之間無法進行JOIN處理,資料庫分割的時候就需要預先考慮這些問題。資料庫分割後,如果一定要進行JOIN處理,就必須要在程式中進行關聯,這是非常困難的。
為有資料更新的表做索引或表結構(schema)變更
在使用關係型資料庫時,為了加快查詢速度需要建立索引,為了增加必要的欄位就一定需要改變表結構。為了進行這些處理,需要對錶進行共享鎖定,這期間資料變更(更新、插入、刪除等)是無法進行的。如果需要進行一些耗時操作(例如為資料量比較大的表建立索引或者是變更其表結構),就需要特別注意:長時間內資料可能無法進行更新。
共享鎖:其他連線可以對資料進行讀取但是不能修改資料,是讀鎖。
排他鎖:其他連線法務對資料進行讀取和修改操作,是寫鎖。
欄位不固定時的應用
如果欄位不固定,利用關係型資料庫也是比較困難的。加欄位在實際運用中每次都進行反覆的表結構變更時非常痛苦的。你也可以預先設定大量的預備欄位,但這樣的話,時間一長很容易弄不清楚欄位和資料的對應狀態(即哪個欄位儲存哪些資料),所以並不推薦使用。
對簡單查詢需要快速返回結果的處理
關係型資料庫並不擅長對簡單的查詢快速返回結構。因為關係型資料庫是使用專門的SQL語言進行資料讀取的,它需要對SQL語言進行解析,同時還有對錶的鎖定和解鎖這樣的額外開銷。這裡並不是說關係型資料庫的速度太慢,而只是想告訴大家若希望對簡單查詢進行高速處理,則沒有必要非用關係型資料庫不可。
關係型資料庫應用廣泛,能進行事物處理和JOIN等複雜處理。相對地,NoSQL資料庫只應用在特定領域,基本上不進行復雜的處理,但它恰恰彌補了之前所列舉的關係型資料庫的不足之處。
NoSQL資料庫
NoSQL資料庫原本就不支援JOIN處理,各個資料都是獨立設計的,很容易把資料分散到多個伺服器上。由於資料被分散到了多個伺服器上,減少了每個伺服器上的資料量,即使要進行大量資料的寫入操作,處理起來也更加容易。同理,資料的讀入操作當然也同樣容易。所以它的優點是易於資料的分散。
提升處理大資料的能力可以通過兩種方式提升效能(縱向)和增大規模(橫向),提升效能指的是通過提升現行伺服器自身的效能來提高處理能力。這需要的費用較高。增大規模指的是使用多臺廉價的伺服器來提高處理能力。它需要對程式進行變更,但由於使用廉價的伺服器,可以控制成本。另外,以後只要增加伺服器的數量就可以了。
典型的NoSQL資料庫
臨時性鍵值儲存(memcached、Redis)、永久性鍵值儲存(ROMA、Redis)、面向文件的資料庫(MongoDB、CouchDB)、面向列的資料庫(Cassandra、HBase)
鍵值儲存
這是最常見的SQL資料庫,它的資料是以鍵值的形式儲存的。雖然它的處理速度非常快,但是基本上只能通過鍵的完全一致查詢獲取資料。根據資料的儲存方式可以分為臨時性、永久性和兩者兼具3種。
臨時性:memcahced把所有資料都儲存在記憶體中,這樣儲存和讀取的速度非常快。
永久性:把資料儲存在硬碟上,與memcached在記憶體中處理資料比起來,由於必然要發生對硬碟的IO操作,所以效能上還是有差距的。
兩者兼具:Redis屬於這種型別。Redis首先把資料儲存在記憶體中,在滿足特定條件(預設是15分鐘一次以上,5分鐘內10個以上,1分鐘內10000個以上的鍵發生變更)的時候將資料寫入到硬碟中,這樣既確保了記憶體中資料的處理速度,又可以通過寫入硬碟來保證資料的永久性,這種型別的資料庫特別適合處理陣列型別的資料,總結來說:
-
同時在記憶體和硬碟上儲存資料
-
可以進行非常快速的儲存和讀取處理
-
儲存在硬碟上的資料不會消失(可以恢復)
-
適合於處理陣列型別的資料
面向文件的資料庫
MongoDB、CouchDB屬於這種型別,它們屬於NoSQL資料庫,但與鍵值儲存相異。
-
不定義表結構:即使不定義表結構,也可以像定義了表結構一樣使用,還省去了變更表結構的麻煩。
-
可以使用複雜的查詢條件:跟鍵值儲存不同的是,面向文件的資料庫可以通過複雜的查詢條件來獲取資料,雖然不具備事務處理和Join這些關係型資料庫所具有的處理能力,但初次以外的其他處理基本上都能實現。
面向列的資料庫:普通的關係型資料庫都是以行為單位來儲存資料的,擅長進行以行為單位的讀入處理,比如特定條件資料的獲取。因此,關係型資料庫也被稱為面向行的資料庫。面向列的資料庫以列為單位,對大量行少數列進行讀取,對所有行的特定列進行同時更新。
面向列的資料庫具有高擴充套件性,即使資料增加也不會降低相應的處理速度(特別是寫入速度),所以它主要應用於需要處理大量資料的情況。另外,利用面向列的資料庫的優勢,把它作為批處理程式的儲存器來對大量資料進行更新也是非常有用的。
面向列的資料庫
Cassandra、HBae、HyperTable屬於這種型別,由於近年來資料量出現爆發性增長,這種型別的NoSQL資料庫尤其引入注目。
普通的關係型資料庫都是以行為單位來儲存資料的,擅長以行為單位的讀入處理,比如特定條件資料的獲取。因此,關係型資料庫也被成為面向行的資料庫。相反,面向列的資料庫是以列為單位來儲存資料的,擅長以列為單位讀入資料。
面向列的資料庫具有搞擴充套件性,即使資料增加也不會降低相應的處理速度(特別是寫入速度),所以它主要應用於需要處理大量資料的情況。另外,把它作為批處理程式的儲存器來對大量資料進行更新也是非常有用的。但由於面向列的資料庫跟現行資料庫儲存的思維方式有很大不同,故應用起來十分困難。