關聯式資料庫與文件資料庫對比
在關聯式資料庫和文件資料庫的對比中,我們通常考慮他們各自擁有下面的優點:
- 支援文件資料模型的主要論點是模式靈活性,由於區域性性它會帶來更好的效能,對於某些應用來說更接近應用程式所使用的資料結構。
- 支援關係資料模型的主要論點是它在聯結操作上的支援,多對一和多對多關係的簡潔表達。
1. 關於程式碼簡潔性的對比
首先需要明確的是,我們無法一概而論地說哪種資料模型地應用程式碼最簡單,這主要取決於資料項之間關係型別。
- 如果應用程式具有類似文件的結構(即一對多關係樹),那麼使用文件模型最為合適。
- 這種情況下使用關係模型會將原本簡單的問題複雜化。
- 文件模型描述文件結構時也有一定的侷限性,比如他們不能直接引用文件中的巢狀項。而必須使用“使用者xxx地職位列表中的第二項”,這樣的語句描述。
- 如果應用程式不需要多對多關係或多對一關係,文件資料庫對聯結支援不足就天生地不是一個問題。
- 如果應用程式確實使用了多對多關係,那麼應當使用關係模型。
- 使用文件模型也不是沒有處理聯結關係的辦法,比如傳送多個請求,在應用程式碼中模擬聯結。但通常這樣做會使得系統程式碼更復雜,效能更差。
- 關係模型天然地更擅長描述多對多關係。
- 對於高度關聯的資料,關係模型比文件模型更加優秀,但實際上圖模型或許是最為自然的解決方案。
2. 文件模型中的模式靈活性
大多數文件資料庫,以及關聯式資料庫中的 JSON 支援,都不會對文件中的資料強制執行任何模式。沒有模式意味著可以將任意鍵值對假如到文件中,並且讀取時客戶端無法保證文件可能包含哪些欄位。
文件資料庫中讀資料的程式碼通常採用某種結構因而存在某種隱式模式,即我們所稱的讀時模式(資料的結構是隱式的,只有在讀取時才解釋)。與此相對的,關係模式的傳統模式我們稱為寫時模式(模式是顯示的,資料保證資料寫入時必須遵循)。
下面給出一個例子,假如當前使用者的全名儲存在一個欄位中,但現在想分別儲存名字和姓氏:
-
在文件資料庫中,我們只需使用新欄位來編寫新文件,並在應用層處理讀取舊文件的情況
if(user && user.name && !user.first_name){ // 處理沒有 first_name 的舊文件 user.first_name = user.name.split(" ")[0]; }
-
在關聯式資料庫中,我們通常需要對錶結構進行更改
ALTER TABLE user ADD COLUMN First_name text; UPDATE users SET first_name = substring_index(name,' ', 1);
實際上,大部分關聯式資料庫在幾秒內也可執行完上面的 ALTER 語句。除了 MySQL 在執行
ALTER TABLE
時要把當前的整張表複製。至於第二步 UPDATE 語句,在大表上執行這個語句在任何資料庫中都可能很慢,通常可以將
first_name
設定為預設值NULL
,在讀取時填充它。
如果集合中的因為某些原因,不具有相同結構,例如:
- 有許多不同型別的物件,並且把每種型別的物件存在各自的表中不太現實。
- 資料的結構由無法控制的外部系統所決定,並且隨時可能改變。
這些情況下,模式帶來的損害可能大於他們帶來的幫助。
3. 查詢的資料區域性性
文件通常儲存為編碼為 JSON、XML 等形式的連續字串。如果應用程式需要頻繁訪問整個文件(例如在網頁上呈現):則文件模式的儲存區域性性會帶來效能優勢。如果按照關係模式的做法,資料被劃分在多個表中,則可能需要多次索引來檢索所有資料,帶來了更多的磁碟 IO,可能會影響效能。
區域性性優勢僅適用於需要同時訪問文件大部分內容的場景。由於資料庫通常會載入整個文件,如果應用只是訪問其中的一部分,則可能會產生浪費。對文件進行更新時,通常會重寫整個文件,而只有修改量不改變源文件大小時,原地覆蓋更新才有效。因此通常建議文件應該儘量小並且避免寫入時增加文件大小。
4. 文件資料庫與關聯式資料庫的融合
近年來,幾乎所有關聯式資料庫系統都支援了 XML。包括對 XML 文件進行本地修改,在 XML 文件中進行索引和查詢等。這樣應用程式可以獲得與文件資料庫非常相似的資料模型。
PostgreSQL、MySQL 等資料庫都對 JSON 文件提供了相應支援。
文件資料庫方面,RethinkDB 的查詢介面支援和關係型類似的聯結,而一些 MongoDB 驅動程式可以自動解析資料庫的引用關係(在客戶端進行高效聯結)。
融合兩種模型是未來資料庫發展的一條很好的途徑。