接續 Day 4 內容
這裡有許多可以比較的點,像容錯能力和如何處理並行執行緒,但最主要的差異點就是 document model 的 schema 彈性較高,且 local 環境下執行效率也比較好,relational morel 則是比較支援 JOIN 及多對一、多對多關係。
如果你的軟體用的資料項目是符合 Tree 那樣的一對多關係,Document Model 會比較簡單,最大的差異點就是不用像 relational model 那樣分成多個 table,也代表不用理會每個 table 各別的 schema 是如何,也降低應用端的程式複雜度。
但如果你的軟體用資料項目是傾向多對多關係,Document Model 可能就不是首選了,有鑑於 document model 對 join 的支援很貧乏,減少 JOIN 的可能方法之一就是做 denormalization (去標準化),或者查詢多次,但如此就會提高應用端的程式複雜度,JOIN 在這就是比較好的選擇了,把多次查詢合成一次,這就是把複雜度移往 database 端的例子。
很難說誰讓程式變的簡單了,要基於應用端資料項目的關係為何,有時使用 graph data model 還可能讓程式更簡單。
Document database 的 schema 是只有在你讀取資料並需要對它做解釋時才會用到,稱做 schema-on-read,可以把它視為一種隱含的 schema,相反的 Relational database 的 schema 就稱做 schema-on-write,這就是明確的 schema 定義了,在你寫入資料時會確保資料符合 schema 所定義的格式。
schema-on-read 很像動態程式語言 (執行時檢查),像 Python、PHP,schema-on-write 則是像靜態程式語言 (編譯時檢查),像 Java、C,你無法斷定說哪種類型的程式語言較棒,同理也是得如此這樣看 data model 的 schema 處理方式。
但是 NoSQL 會紅也不是沒有道理的,schema-on-read 在某種程度上帶來非常大的彈性,舉例來說,目前你的 user table 裡,完整的 name 是儲存在一個欄位裡,然後你需要把 name
切成 first_name
和 last_name
2 個欄位儲存,在 Document database 裡,你可以直接在新資料儲存裡加上這 2 個欄位,然後只要新增下面這段 code,舊的資料在讀取時也就有這 2 個欄位了。
if (user && user.name && !user.first_name) {
// Documents written before Dec 8, 2013 don't have first_name
user.first_name = user.name.split(" ")[0];
}
但在 Realtional database 該怎麼做呢?你得要變更 data schema 新增欄位然後 update 舊資料,
ALTER TABLE users ADD COLUMN first_name text;
UPDATE users SET first_name = split_part(name, ' ', 1); -- PostgreSQL
UPDATE users SET first_name = substring_index(name, ' ', 1); -- MySQL
不用說 alter table 是一種很昂貴的操作,database 可能會變慢也有可能短期內無法提供服務,update 操作亦同。
schema-on-read 的一大優點就是你不用保持所有的資料都是同一種資料架構,例如你的資料來源是外部系統,你無法控制對方什麼時候改變資料型態,在這情況下,Relational database 的 schema 造成的傷害會比幫助多,之後會談到如何做到 document database 的 schema 進化 (evolution)。
documnet 在儲存時通常會存成連續的字串,像 JSON、XML 或變體的 binary 字串 (MongoDB 的 BSON),如果你的軟體是需要一整個 documnet 做事情的,例如產生網頁,這時 storage locality (儲存區域性) 就有優勢了,不用像 前一天 的圖 2-1 那樣,多個 table 代表會有更多的 index 查找跟更多的查詢時間。
這裡值得提出的一點是把相關的資料為了 locality 原因而 group 起來並不侷限在 Documnet Model 而已,像 BigTable 的資料模型 column-family 就是類似概念 (用在 HBase 和 Cassandra),未來會提到更多。
現在 MySQL 和 PostgreSQL 都開始支援 JSON 和 XML 這種 documnet 類型的資料型態,在 document database 裡,RethinkDB 在 query 中支援了 relational-join , MongoDB 則是用 lookup 的方式做到 join 的情景,但一定比 realtional database 來的慢。
未來 database 一定是往混合的道路走,工程師就有更好的工具完成資料模型的設計了。
[Day 6] Data Model (3) - Graph-Like Data Model