關係型資料庫儲存多維指標資料

2022-09-15 21:01:41

什麼是多維指標資料?

指標是一個統稱概念,可以細分為 原子指標派生指標。 以 某企業近一週上海地域的銷售金額 為例,整體是一個派生指標,其中的 銷售金額 是原子指標;近一週 是時間,企業地域 是維度。

可見,指標資料由三部分組成:

  • 時間
  • 維度
  • 數值

其中,維度可以是一個或多個,也可以是零個,簡稱為多維。

什麼是關係型資料庫?

典型的關係型資料庫就是 MySQL

使用時,需要先根據業務設計好資料模式:

  • 資料庫中有哪些資料表
  • 資料表中有哪些欄位

然後,建立相應的資料庫和資料表;最後,儲存業務資料。

關係型資料庫會有一個特殊的 約定:資料模式是相對固定的。業務不發生變化的情況下,資料模式不會輕易發生變化。

使用關係型資料庫儲存多維指標資料會有什麼問題?

不同的業務會有不同的指標,每一個業務可以單獨建立一個資料庫,這個比較好理解。

每一個指標都會有時間和數值,但是不同的指標之間,它們的維度名稱和維度數目卻可能是不同的。

最直接的設計:

  • 每一個指標單獨建立一個資料表,位於某個業務資料庫
  • 資料表除時間和數值欄位外,根據指標的不同,建立若干維度欄位

假設某個指標有三個維度:a、b 和 c,表結構如下所示:

timestamp a b c value
2022-09-15 00:00:00 a1 b1 c1 1
2022-09-15 01:00:00 a2 b2 c2 2
2022-09-15 02:00:00 a3 b3 c3 3

timestamp 表示時間,value 表示數值,a、b 和 c 表示維度。

問題很明顯:

  • 如果某個業務擁有成千上萬個指標,就需要建立成千上萬個資料表。無論是預先建立資料表,還是隨著指標的新增動態建立新的資料表,如此數目龐大的資料表是不能接受的。
  • 固化的資料表結構不能很好地應對指標的維度名稱和維度數目發生變化的場景。

受限於業務方的部署環境,僅支援關係型資料庫 MySQL;而且業務方不能接收一個業務指標一個資料表的粗暴設計。

思考

業務指標的數目是不可控的,但業務指標的維度數目是相對可控的,我們是否可以按維度數目建立 指標表,畢竟絕大多數資料視覺化元件最多支援三維。

比如:

  • 維度數目為 0 的指標表
  • 維度數目為 1 的指標表
  • 維度數目為 2 的指標表
  • ...

假設維度數目為 3 的指標表,表結構如下所示:

id timestamp d1 d2 d3 value
m1 2022-09-15 00:00:00 a1 b1 c1 1
m2 2022-09-15 01:00:00 a2 b2 c2 2
m3 2022-09-15 02:00:00 a3 b3 c3 3

id 表示指標 ID,用於唯一標識指標;d1 、d2 和 d3 分別表示維度1、維度2 和 維度3。

一張資料表中可以儲存多個相同維度數目指標的資料,如:m1、m2 和 m3。儲存指標資料時,只要按指標的維度數目,將指標資料儲存到相應維度數目的指標表中即可。指標表可以根據業務可能的最大維度數目預先建立,業務維度數目需要擴充套件時,僅需要新增有限的幾張特定維度數目的指標表即可。

還不夠!

指標有維度的情況下,指標表僅支援按指標維度次序,依次儲存和查詢維度1、維度2、... 的維度資料,並不知道具體的維度名稱是什麼。

考慮到業務希望指標發生變化時,歷史資料可追溯,同一個指標需要有多個版本。

也就是說,我們需要知道:

  • 指標的版本有哪些
  • 指標的某個版本有哪些維度,維度名稱是什麼
  • 指標的某個版本有哪些資料

我們可以:

  • 建立一張 版本表,儲存指標有哪些版本
  • 建立一張 維度表,儲存指標的某個版本有哪些維度(名稱)
  • 根據維度數目建立若干張指標表,儲存指標的某個版本的指標資料

可行!

儲存方案

版本表

id version
m1 1
m2 1
m1 3

id 表示指標 ID,version 表示版本號。

版本表儲存著指標和版本的對應關係,可以查詢指標的歷史版本記錄,也可以查詢指標的最新版本。

維度表

id version name
m1 3 a1
m1 3 a2
m1 3 a3

id 表示指標 ID,version 表示版本號,name 表示維度名稱。

維度表儲存著指標/版本和維度名稱的對應關係,可以按指標 ID 和指標版本查詢維度名稱列表,多個維度名稱的順序按維度名稱儲存順序依次排列。

指標表

id version timestamp d1 d2 d3 value
m1 3 2022-09-15 00:00:00 a1 b1 c1 1
m1 3 2022-09-15 01:00:00 a2 b2 c2 2
m1 3 2022-09-15 02:00:00 a3 b3 c3 3

指標表儲存著指標資料。注意,維度1、維度2 和 維度 N 的表現形式。

儲存指標資料

新增指標時,使用 Unix 時間戳作為版本號,儲存指標 ID 和 版本至版本表;如果指標有維度,儲存指標ID、版本號 和維度名稱至維度表,如果維度有多個,需要按照維度排列順序依次儲存多條記錄。

修改指標時,如果修改後的指標維度名稱列表和維度表中該指標最新版本的維度名稱列表數目或內容不一致,需要和新增指標一樣,儲存該指標新的版本號和維度名稱列表。

儲存指標資料時,獲取維度表中該指標最新版本的維度名稱列表,即可知指標維度數目;根據維度數目選取指標表,將指標資料儲存至該指標表,維度名稱需按順序依次儲存至維度1、維度2、...。

查詢指標資料

  1. 根據指標 ID 查詢版本表,獲取該指標的最新版本號,或者直接指定某個版本號;
  2. 根據指標 ID 和版本號,查詢維度表,獲取該指標的維度名稱列表和維度數目;
  3. 根據指標的維度數目,選取指標表;
  4. 根據指標 ID 和版本號,查詢指標表,獲取該指標的資料;也可以使用時間或維度過濾指標資料。
  5. 使用 2 中獲取指標的維度名稱,替換 4 中獲取的指標資料中的維度1(d1)、維度2(d2) 、...。