自從NoSQL概念橫空出世,關係數據庫彷佛就成了衆矢之的,彷佛一晚上之間,關係數據庫和SQL就成了低效,高成本,速度慢的數據處理模式的代名詞。在不少地方都能看到相似:」個人項目初創,應該選擇什麼NoSQL產品才能快速的開發?」這樣的問題。
正因有人提出這樣的問題,才堅決了我把這篇文章放在了第一章的決心。主要的目標是但願藉助這樣一個形式,讓你們可以比較清晰的認識到相似NoSQL,SchemaFree,RDBMS,CAP,BASE等等概念的本源,並瞭解到他們面對的主要場景,從而避免亂花漸入迷人眼的尷尬,知其然而知其因此然。
其實,軟件中所謂的對象,結構體,實體,關係等概念,都只是對現實生活中的一種抽象。由於人類太過眇小,眇小到沒法真正的理解和模擬這個世界,因此不得不創造出一些概念,過濾掉具體的細節而只關心他們所須要關心的事情。這就產生了各類各樣的抽象。
而SQL和關係模型,就是針對數據之間的「關係」而進行的一種抽象。
簡單來講,他將一切事物都抽象爲關係,並經過集合運算的方式規定了關係之間的運算過程,也所以更爲嚴謹。好比,描述一輛車有四個輪子和四扇玻璃,那麼就能夠創建三張表格,一張存車的屬性,一張存玻璃的屬性,一張存輪子的屬性,而且在輪子和玻璃的表格中,冗餘車的惟一標示。這樣就能夠完成關係描述。若是要讀取車A.id=5車子的左前方輪子的出廠號碼標示,作法通常是:查詢輪子表,找到車子id=5的而且標有左前方屬性的那行數據,讀取他的出廠號碼。
瞭解了關係模型,咱們再來看看在關係模型產生以前,你們常用的層次模型吧。
層次模型其實也是很是簡單的一類描述,還以車爲例,一輛車有惟一的標示(能夠是個id,也能夠只是個入口引用),而後車節點有兩個子節點,一個是輪子集合節點,一個是玻璃集合節點,而後,輪子集合節點有四個節點,分別表示四個輪子,而玻璃集合有四個節點,分別標示四扇玻璃。若是要讀取車A.id=5車子的左前方輪子的出廠號碼標示,作法通常是:找到頂節點車A,而後查找該節點的子節點,輪子集合節點,而後遍歷4個子節點,找到標有左前方屬性的車輪,讀取其出廠號碼。
從上面簡單的例子對比來看,相信你們馬上就能看出關係模型與傳統的層次or表格模型的最大差異。也就是
用戶再也不須要關注從車->輪子集合->輪子自己,這個存取路徑,
只須要關注於核心的查詢邏輯(車子id=5,車輪屬性是左前方),就能夠馬上找到數據了。使用關係模型,由於模型相對的比較簡單,而且數學證實比較嚴密,因此很快被你們接受。
所以在市面上已經不多出現層次模型or網狀模型了。
在互聯網時代以前,數據庫的研究領域更多的集中在關係模型與前端業務開發模型不匹配這個問題上,衆所周知的,在面向對象的語言產生以後,繼承,多態,充血模型已經成爲了程序語言的標配,咱們在這裏不去討論是面向對象好,仍是函數式編程好這樣沒結論的問題,只來簡單的瀏覽一下面向對象與關係模型的阻抗失配問題便可。
若是你們寫過業務邏輯,必定也會以爲把數據庫裏的數據轉變爲程序對象是一件蛋疼無比的事情吧。將面向對象裏面的繼承和組合這類概念硬套到關係數據庫上,須要耗費比較大的精力才能完成。
爲了解決這些問題,一種思路是在程序層作這個ORMapping的轉換,這類工具主要是hibernate、ibatis等工具。另一個思路是在數據庫層面作這件事,好比oracle一直宣傳本身是ORDBMS。甚至甚至,連腳本語言框架好比ROR,django的核心目標之一也就是解決這個阻抗失配的問題~
由於相似java/c++/.net這樣的語言是靜態編譯的,因此就必需要求用戶要在代碼中明確的定義對象的屬性名字和類型,而在數據庫內,也有一套對應的列名和數據庫類型信息。一張表有50多個字段,每次字段變動,都必須保證用戶代碼內的對象內的屬性和數據庫中的數據準確對應。這很是消耗時間,也很是容易錯。
爲了解決這個問題,要麼是從程序代碼生成關係模型,要麼是從關係模型反向生成程序代碼。這兩種方式都會面臨程序邏輯與關係模型不匹配的問題,因而寫ORMapping就成了一件蛋疼無比但又不得不作的事情。
爲了自動化,有大量的工具組件出如今這裏,好比hibernate,好比ibatis,他們主要做用就是將咱們的對象模型轉換爲關係模型,不過這類工具最大的問題就是,學習工具自己的成本很高,甚至高於本身去作對象關係映射自己,並且常常會由於對ORMapping掌握的不夠精深,形成不少低效的查詢,拖慢了總體性能的問題。
還有一些人爲了偷懶,放棄使用對象bean來表示數據庫中數據。他們通常會採用Map映射來表示數據庫中一行數據,使用這種方式,Map的key就是列的名字,value就是列的值,若是要表示多行數據,那麼就是一個List<Map>的結構。使用這種結構,程序就能夠自動的根據數據庫給出的列名原信息來自動生成Map結構。但這種方式的問題是,丟失了面向對象所帶來的良好的封裝特性,通過多層傳遞與處理後,用戶很難辨識哪些是數據中間過程數據,哪些是數據庫原始數據。數據Map對象會膨脹的很是厲害,以致於沒法管理。
腳本語言的核心目標之一也就是解決這個阻抗失配的問題,腳本語言由於是動態編譯的,因此動態對一個對象增長或減小屬性變得很是簡單而清晰,因此對象內的數據能夠直接根據數據庫內的數據進行內省得到,不在須要人工維護,同時又不會出現由於Map結構所致使的代碼結構不清晰的問題,因此ROR這類的工具能夠直接進行對象關係映射,極大地提高了小業務系統的生產力。
惋惜,對象數據庫和xml數據庫,都沒有造成一統天下的新浪潮,一直不瘟不火的緩慢發展着。
隨着互聯網的爆發式發展,數據庫概念領域又一次發生了搖擺,伴隨着互聯網的特殊需求,一批有着新鮮血液的NoSQL數據庫涌現了出來,層次模型又從封印中甦醒,站在了你們面前。
這裏就天然而然會有一系列的疑問產生了出來,爲何層次模型變種的NoSQL會出現並獲得了一些人的認同?他知足了什麼需求?關係模型在什麼地方不能知足你們的需求了?
那麼,咱們就從應用場景出發,嘗試回答一下這些問題吧。