iT邦幫忙

2024 iThome 鐵人賽

DAY 17
0
Software Development

Datomic,內建事件溯源的資料庫。系列 第 17

先從 Datalog 談起 -- part 12 (cross database join)

  • 分享至 

  • xImage
  •  

在微服務的設計模式裡,每個服務獨立資料庫 (Database per service) 是一種常用的設計模式。 (註1) 要採用這種模式,若搭配 SQL 資料庫,通常有三種作法:

  1. 每個服務對應數張專用的資料表
  2. 每個服務對應一個專用的資料表命名空間 (schema)
  3. 每個服務對應一個專用的資料庫

選用 1, 2 帶來的額外開發成本會小得多,而 3 的話則有最完整的資源隔離。然而,無論服務的邊界切得如何完美,既然是同一個系統,往往多少都會有需要與其它服務的資料聯合起來一起查詢的時候。當這種需求發生時,1,2 這兩個解法依然允許 SQL join 直接執行在不同的服務對應的資料上。然而,如果選擇的作法是 3 的話,開發的成本就很高了。

Datalog 的跨資料庫查詢

在 Datomic ,並沒有提供類似資料表命名空間 (schema) 的語法,換言之,選項只有 1, 3 兩種。另一方面,Datalog 卻又提供語法,可以讓我們做到跨資料庫的查詢,換言之,如果是要實作微服務的設計模式,搭配 Datomic 資料庫的話,可以大方地採用 3 做為預設選項,而不太需要操心,將來暴增的查詢困難。

先來看個 Datalog 跨資料庫查詢的範例吧:

;; All revenue but orders in database b
[:find ?o ?r
 :in $a $b
 :where
 [$a ?o :order/revenue ?r]
 ($b not [?o :order/revenue])]

在某公司,a 資料庫記錄了所有訂單對應的利潤。然而,凡是有退款、壞帳等疑慮的訂單,則會記錄在 b 資料庫裡。上頭的查詢是『找出 a 資料庫裡所有的訂單與對應的利潤,但是去除在 b 資料庫裡出現的訂單。』。

語法的變化只有出現在 :in 子句與 :where 子句,都增加了資料源變數 (source variable)。在 in 子句裡的 $a$b 就是資料源變數,這種變數代表的是資料的來源,通常是一個資料庫,但是也可以是數組的陣列。在第一個 :where 子句裡的 $a,它的意思是這個子句的比對只作用在 $a 資料庫;而第二個子句裡的 $b,它的意思是這個子句的反向比對只作用在 $b 資料庫。

:in 子句後的變數

整理一下,in 子句出現過的變數,目前為止已經介紹了三種:

  1. 一般綁定變數。它必須是 ? 起頭的命名。
  2. 資料源變數。它必須是 $ 起頭的命名。
  3. 規則變數。它會是 %

省略資料源變數

資料源變數主要的功能是限制子句作用的範圍。當只有一個資料源變數時,也就意謂著這不是跨資料庫查詢時,也就不用思考什麼範圍的問題了,因為作用的範圍就一定是預設的資料庫。也因此,Datalog 很貼心地設計成:「只有一個資料源變數時,資料源變數在子句裡可以省略。」

資料源變數的語法

再仔細看觀察上方的範例,我們可以發現,資料源變數在 :where 子句裡的用法很一致。

  1. 它可以使用在 not 子句。資料源變數要加在最左邊。
  2. 它可以使用在資料模式 (data pattern) 子句,也是一樣加在最左邊。

但是,資料源變數還可以加在其它的子句裡嗎?比方說,如果我們想對規則 (rules) 也套用資料源變數呢?可以的,也是一樣加在最左邊。

在下方的例子,規則表達式子句 ($ actor-movie ?name ?movie-title) 就使用了資料源變數。

(def rules
  '[[(actor-movie ?name ?title)
    [?p :person/name ?name]
    [?m :movie/cast ?p]
    [?m :movie/title ?title]]]])

(d/q '[:find ?name
       :in $ % ?movie-title
       :where ($ actor-movie ?name ?movie-title)]
     db rules "The Terminator")

整理一下,資料源變數可以這樣子使用:

  1. 它可以應用在 not, not-join, or, or-join 子句。
  2. 它可以應用在資料模式 (data pattern) 子句。
  3. 它可以應用在規則表達式 (rule expression) 子句。
  4. 只有一個資料源時,它可以省略。要加在子句裡的時候,一律加在最左邊。

註:

  1. Database per service

其它資源

  1. 歡迎訂閱 PruningSuccess 電子報,主要談論軟體開發、資料處理、資料分析等議題。
  2. 歡迎加入 Clojure 社群

上一篇
先從 Datalog 談起 -- part 11 (rules)
下一篇
先從 Datalog 談起 -- part 13 (SQL window function)
系列文
Datomic,內建事件溯源的資料庫。30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言