尤川豪   ·  5年前
445 貼文  ·  275 留言

彈性資料庫架構:存 JSON format 與 EAV model 的優劣比較

直接用 text 存 json 很糟糕(MySQL 5.7 之前)

個人開發經驗,有幾點很糟糕:

  • 以 text 格式存,無法在 database level 做任何格式檢查,很不踏實,也許根本存到 invalid JSON format data
  • 很難 query,基本的 sql WHERE 都無法寫,只能用 text search 之類的硬 query

使用 EAV model 很糟糕

個人開發經驗,有幾點很糟糕:

  • 資料四散,很煩,屬於同一個 entity 的 attribute 會以多個 row 的形式散在 table 內,出現在一起比較好
  • 需要不斷使用 JOIN,寫起來很煩,效能也有問題吧?
$reviews = \Modules\HavaCore\Entities\ReviewCell::findMany(DB::table('review_cells')
    ->select('review_cells.id')
    ->join('entities', 'review_cells.entity_id', '=', 'entities.id')
    ->groupBy('review_cells.entity_id')
    ->groupBy('review_cells.user_id')
    ->where('entities.topic_id', HavaCore::getTopic()->id)
    ->get()->pluck('id')->all())->sortByDesc('created_at');

MySQL 5.7+ 之後終於原生支援 JSON 了,很有幫助

MySQL 5.7+ 之後終於可以支援 JSON,使用 -> operator 就可以下 query 了

在 laravel 的話就是

查詢

$users = DB::table('users')
                ->where('options->language', 'en')
                ->get();

$users = DB::table('users')
    ->where('preferences->dining->meal', 'salad')
    ->get();

甚至是

$users = DB::table('users')
    ->whereJsonContains('options->languages', ['en', 'de'])
    ->get();

更新

DB::table('users')
    ->where('id', 1)
    ->update(['options->enabled' => true]);

效能比較與分析

請看另一篇

https://devs.tw/post/53

  分享   共 4,506 次點閱
按了喜歡:
共有 4 則留言
Connor Hsu   ·  5年前
0 貼文  ·  7 留言

雖然這篇講的是用什麼存 json,我個人還是很排斥存 json,即使 mysql5.7 之後支援 json format 不需要 parse text,還是會把它當作 workaround,用了之後也會把它技術債看待。

原因很簡單:彈性跟穩定性通常都是互斥的,有本老書叫 data modeling essentials 也講到要考慮這個原則(事後才去估狗到的)

某個欄位可以隨意增加 json 裡面的 key,因此開發很快,那就表示其他人要承擔資料不確定性的風險

有些情況下我們會犧牲穩定性,比如內部實驗演算法模型,越快越好,可能最後也不會上線;有些情況下我們會犧牲彈性,因為這個資料庫的服務重要到完全不能出差錯。

像這種 trade-off 通常都會默默地被選了彈性的那一邊,因為老闆想要快,有些工程師也會誤以為自己開發很快,事實上是拿其他team 跟之後維護人員的時間換來的;如果選了彈性的那一邊,那應該要意識到做了這個選擇,在需要產線化之前安排重構、或是用其他方式(文件、註解、額外的檢查等等)來管理這個彈性的 schema,否則就會出現「跟地下錢莊借錢卻還沾沾自喜以為不用還」的情形

(待續)

 
按了喜歡:
尤川豪   ·  5年前
445 貼文  ·  275 留言

用 RDBMS 的確應該盡量避免這樣存 幾乎在任何情況下都要避免這樣存

我是因為在使用 PHP/Laravel/MySQL 開發類似 CMS 的系統

無法得知使用者/開發者會需要什麼欄位 所以 schema 定不出來

所以才研究這個主題

 
按了喜歡:
Laurence Chen   ·  5年前
0 貼文  ·  1 留言

有一個 clojure 語言常用資料庫 Datomic ,它有一些特性: (1) query language 是 Datalog (2) entity 可以很彈性地動態加入 schema 。

如果要用 Datomic 來做 web application 開發,可以考慮使用 luminus framework https://github.com/luminus-framework/luminus-template

這邊要呼應原本的貼文的一點是 Datomic-free 的版本,是跑在 H2 Database 上。底層的實現就是用 EAV model 來做。我個人有一些使用 Datomic 的經驗,用 datalog 來 query ,基本上我覺得還算容易,表現能力也滿強的。

 
按了喜歡:
尤川豪   ·  5年前
445 貼文  ·  275 留言

非常謝謝你的介紹!

這些技術我都是第一次聽到,大開眼界了,找時間來研究一下它們!

您的留言
尤川豪
445 貼文  ·  275 留言

Devs.tw 是讓工程師寫筆記、網誌的平台。隨手紀錄、寫作,方便日後搜尋!

歡迎您一起加入寫作與分享的行列!

查看所有文章