關系型數據庫與Key-value型數據庫Mongodb模式設計對比
MongoDb 相比于傳統的 SQL 關系型數據庫,最大的不同在于它們的模式設計( Schema Design )上的差別,正是由于這一層次的差別衍生出其它各方面的不同。
我們可以簡單的認為關系型數據庫由數據庫、表(table)、記錄(record)三個層次概念組成,而在構建一個關系型數據庫的時候,工作重點和難點都在數據庫表的劃分與組織上。一般而言,為了平衡提高存取效率與減少數據冗余之間的矛盾,設計的數據庫表都會盡量滿足所謂的第三范式。相對的,可以認為MongoDb由數據庫、集合(collection)、文檔對象(Document-oriented、BSON)三個層次組成。MongoDb里的collection對應于關系型數據庫里的表。當然,不要期望collection會滿足所謂的第三范式,因為它們根本就不在同一個概念討論之內。類似于表由多條記錄組成,集合也包含多個文檔對象,雖然說一般情況下,同一個集合內的文檔對象具有相同的格式定義,但這并不是必須的,即MongoDb的數據模式是自由的(schema-free、模式自由、無模式)。
以一實例來說,假設我們需要設計一個小型數據庫來存儲“學生、地址、科目、成績”這些信息,那么關系型數據庫的設計如圖1所示,而Key-value型數據庫的設計則可能如圖2所示。
圖1、關系型的數據庫設計
圖2、Key-value型的數據庫設計(直接借用的mongodb官方圖)
對比圖1和圖2,在關系型的數據庫設計里劃分出了4個表,而在Key-value型的數據庫設計里卻只有兩個集合。如果說集合與表一一對應的話,那么圖2中應該也有4個集合才對,為什么可以把本應該是集合的address和scores直接合入了集合students中?原因就在于在Key-value型的數據庫里,數據模式是自由的。
以scores來說,在關系型的數據庫設計中將其單獨成一個表是因為student與score是一對多的關系,如果將score合入student表,那么就必須預留最多可能的字段,這會存在浪費,并且當以后新增一門課程時擴展困難,因此一般都會將score表單獨出來。而對于Key-value型的數據庫就不同了,其scores字段就是一個BSON,該BSON可以只有一個for_course,也可以有兩個、三個、任意個for_course,其固有的模式自由特性使得它可以將score包含在內而無需另建一個score集合。
對于與student為一對一關系的address表也可以直接合入student,無需擔心address的擴展性,當以后需要給address新增一個province字段,直接在數據插入時加上這個值即可。
當然,對于與student成多對多關系course表,為了減少數據冗余,可以將course建立為一個集合,同關系型的數據庫設計中類似。
對比于關系型的數據庫,在Key-value型的數據庫里將數據合入一起有幾大好處:首先,數據檢索時沒有了進行表間連接(join)的巨大開銷(雖然目前MongoDb中沒有join的概念);其次,合入一起的數據在磁盤上的存放也更容易在一起,因此數據的讀取/寫入都更快速。另外,無需擔心擴展性問題,Key-value型數據庫的自身特性使得字段的增刪改十分容易。