報表機制 - 重新思考 Rails 架構
報表功能也是非常常見的情境,大多數時候我們都會直接使用 Rails 的資料庫內容,搭配 JOIN 類型的查詢進行處理,然而這並不總是個好辦法。
減少重複
在工程師學習的經驗中,我們很常會聽到 Reuse(重用)的概念,也盡力的在開發過程中進行實踐,資料表正規劃也是類似的概念,我們都在嘗試減少「重複」
在正確的情境下進行這樣的處理並沒有問題,然而我們也很常誤用這樣的概念,最後造成實作有嚴重的耦合,逐漸走向難以維護的困境。
實際上,一定程度的重複是可以被接受的。我們會想減少重複是希望有「Single source of truth(SSOT)」的效果,假設只有一個資料來源就不容易出錯。
然而,在較大跟複雜的系統,如果我們要加快業務(Transaction)的處理的速度勢必要放棄「短時間」內的一致性,以最終一致性(Eventual consistency)為目標,那就有可能需要將同樣的資料複製給不同節點「並行」的進行處理。
OLAP & OLTP
大多數時候使用 Rails 開發的都是 OLTP(線上交易處理)類型的任務,然而報表是屬於 OLAP(線上分析處理)的範疇。
舉例來說,我們想要對某個商品下單,可能會需要快速的將商品資訊、使用者資訊等等組合處理,最後給出是否可以下單的情境。然而,如果是要分析某個使用者過去一年的交易行為,將這些資料組合起來的成本是非常高的,假設能夠在一張資料表就取得所有的資料一次做比較,那就相對的容易。
以 PostgreSQL 來說,就有提供 Materialized View 的機制,可以定期對特定的 SQL 查詢結果保存起來,用於後續的資料分析。
假設我們希望使用者可以快速的進行交易,又需要可以讓這個系統能夠分析使用者的行為,我們可能會有兩種不同職責的資料表(或不同資料庫)保存重複的內容。因此,資料庫的正規化與否,以及是否要消除重複,會根據應用的情境而改變。
當時我們耗費大量力氣製作複雜的 SQL 來滿足查詢需求,仍然很慢的情況下,客戶才接受搭建另一個資料庫專職負責報表的機制,用於緩解查詢緩慢以及難以維護的狀況。
客製化報表
除了上述的查詢問題外,客製化報表也是一個非常大的挑戰。因為每個人想看到,或者需要看到的內容是不同的,因此會需要設定他們想要的呈現方式。
假設是以 OLTP 的方式來處理,我們就需要動態的去組合出所需的 SQL 查詢在不同資料表取得資料,並且根據使用者的設定呈現出期望的報表內容。
然而,大多數情況是針對某種「標準」的報表,隱藏掉不必要的欄位只留下必要的內容進行呈現,這也對應到 OLAP 的特性,我們所需處理的通常會是隱藏欄位跟合併多列資料進行呈現,如此一來在報表的產生上也變得容易不少。
如果對這篇文章有興趣,可以透過以下連結繼續閱讀這系列的其他文章。
- 軟體架構的挑戰 - 重新思考 Rails 架構
- 資料驅動設計 - 重新思考 Rails 架構
- 複雜的操作 - 重新思考 Rails 架構
- 時區換算 - 重新思考 Rails 架構
- 報表機制 - 重新思考 Rails 架構
- 通用化功能 - 重新思考 Rails 架構
- ActiveRecord 的限制 - 重新思考 Rails 架構
- 領域驅動設計 - 重新思考 Rails 架構
- 從架構到設計 - 重新思考 Rails 架構
- 重復使用的反思 - 重新思考 Rails 架構
- 釐清脈絡 - 重新思考 Rails 架構
- 劃分邊界 - 重新思考 Rails 架構
- 職責劃分 - 重新思考 Rails 架構
- 架構規劃 - 重新思考 Rails 架構