五十年前的一樁公案:數據庫關係模型的流行史(上)

1970年,埃德加·科德(Edgar F. Codd)提出了數據庫的關係模型,至今還是數據庫領域的事實標準。html

這個模型在今天看來理所固然,以致於幾乎沒有文章講清楚它是怎麼成功的。程序員

我但願經過談一談五十年前的這一樁公案,給今天在NoSQL與NewSQL浪潮中航行的咱們一些啓發。算法

上篇側重於科普,熟悉關係型數據庫的讀者,能夠直接跳到最後的結論,但請必定關注明天發佈的下篇——那纔是個人重點。數據庫

瓜熟蒂落的第一個問題是,在科德提出關係模型的時候,別人在用什麼?segmentfault

當時的明星產品是IBM的一款層次模型的數據庫,叫IMS。後端

層次模型其實就比如文件夾,好比下面的結構就存儲了兩個小動物吃了多少食物的信息。code

.
├── 青菜, 大櫃子
│   ├── Zoom, 🐻, 10歲, 50千卡
│   └──  Zip, 🐿️,  9歲, 100千卡
└── 年糕, 小櫃子
    └── Zoom, 🐻, 10歲, 200千卡

這樣的存儲方式最大的問題是信息重複。好比這裏,在兩個食物的「文件夾」下都存了「Zoom是隻10歲的熊」這一信息。htm

重複會浪費存儲空間,要知道五十年前人們還在用兆字節(MB)來衡量磁盤的大小。ip

同時重複就對信息的一致性提出了要求。要是加一條Zip吃年糕的記錄,但在記錄的時候把年齡記成了8歲,哪一個纔算是對的呢?資源

還會有人注意到,這樣的表達沒法記錄還沒有進食的小動物。這倒不難解決,加個假的(dummy)食物就好。

其時科德也是IBM的員工,深知IMS數據庫的痛點。於是纔有了今天的主角,關係模型的橫空出世。

在關係模型中,上面的例子能夠被表達爲三個關係。

食物信息:
青菜, 大櫃子
年糕, 小櫃子

小動物信息:
Zoom, 🐻, 10歲
 Zip, 🐿️,  9歲

進食信息:
青菜, Zoom, 50千卡
青菜,  Zip, 100千卡
年糕, Zoom, 200千卡

這裏的關係(relation)的說法來自集合論,指的是幾個集合的笛卡爾積的子集。好比第一個關係就是(青菜, 年糕)×(大櫃子, 小櫃子)的一個子集。

在以前的層次模型的數據庫,用戶能夠通寫簡單的命令,遊歷一個有層次的樹,解決諸如「吃青菜的小朋友年齡分別是多少」之類的問題。

在關係模型中,這個問題涉及到了兩個關係:小動物信息和進食信息。這時就得用到關係的一種操做——鏈接(join)。顧名思義,鏈接後就變成了以下:

青菜, Zoom, 🐻, 10歲, 50千卡
青菜,  Zip, 🐿️,  9歲, 100千卡
年糕, Zoom, 🐻, 10歲, 200千卡

而後只要找到有青菜的這幾行的年齡便可。

說了這麼多,雖然數據是不重複了,但怎麼感受新的模型比以前的更麻煩了呢?別急,接着看。

這時候用戶有了個新的問題:「Zoom要去哪些儲藏食物的地方?」。

若是用層次模型,這跟剛剛的問題徹底不同,須要寫另一個程序。但對於關係模型來講,就只要換成鏈接食物信息和進食信息兩個關係就行了。

這個簡單的例子其實還不足以體現關係模型的強大。當有更多的記錄類型(如儲藏地點信息、飼養員信息)時,用層次模型的程序員可能完全陷入了混亂,關係模型仍是以不變應萬變。

(注意這裏的模型更多指的是表達上的一種語言,而非實際的存儲和訪問形式。對此在下篇會有更詳細的說明。)

這個新的模型爲描述數據的結構、描述要解決的問題,提供了更強大、更靈活的表達能力。

科德應該是預料到,隨強大功能而來的是,要實現它須要的更復雜的程序。

因此他指出,數據庫的使用者應該只負責用關係模型描述要解決的問題(操做集合),具體用什麼算法解決(操做數據),就交給數據庫軟件的開發者去操心吧。

今後數據庫的使用者(後端程序員、數據庫管理員)與數據庫系統的開發者走上了不一樣的道路。

對於使用者來講,「傻瓜式」數據庫成爲了可能。他們能夠專一於實際應用的開發,只要把數據庫的問題抽象成關係和關係的運算,而不用糾結於底層的實現,無疑解放了生產力。

對於開發者來講,這對數據庫的功能提出了更高的要求,但這同時也讓它更加普適、更加好用,從而收穫了更大的市場。有了錢就有更多人才和資源,這個領域也愈來愈精深。

這個故事這麼寫,就像是個無比正能量的輝格史。可實際上,關係模型並非一開始就時今天的樣子,在提出後也長期爭議不斷,十幾年後纔算是奠基了江湖地位。這就是下一篇的內容了。

本文首發於個人博客「青菜年糕湯」上。我每週會寫一篇技術或非技術的原創博文,不按期選擇性轉發到segmentfault。想要第一時間讀到完整的文章(如《聊天機器人爲何這麼難?詢事不考其終,興事不加屢省》),不妨掃描博客中的二維碼關注個人公衆號。

相關文章
相關標籤/搜索