[Day 5] 各種類型的 Database（二）

erichung0404
2024-08-05 18:10:07

前篇簡單介紹了 RDBMS, NoSQL Database, Object Storage 的特性與適用場景

NoSQL Database 還可以再根據儲存方式細分, 今天會介紹以下幾種常見的

Column-based database

Key-value store

Document-oriented database

Time-series database

Column-based database

和名字一樣, 相較於 RDBMS 是列儲存 (row-based), Columnar 是行儲存 (column-based)
好處是可以只搜尋感興趣的欄位, 而不需要讀取無關的部分, 加速查詢時間

舉例來說

| name  | age | gender |
|-------|-----|--------|
| Amy   | 20  | f      |
| Brian | 16  | m      |
| Chloe | 18  | f      |
| David | 22  | m      |

如果我們想要撈出所有的女性
列儲存需要從左 (name) 到右 (gender) 掃過所有欄位, 即使我們的條件只有 gender 這一行, 所以比較沒有效率

1. 讀取 Amy, 20, f -> 符合條件

2. 讀取 Brian, 16, m -> 不符合條件

3. 讀取 Chloe, 18, f -> 符合條件

4. 讀取 David, 22, m -> 不符合條件

行儲存則是直接定位到條件指定的欄位進行查詢, 所以比較有效率

1. 讀取 gender 列: f, m, f, m

2. 找出 f 對應的 index

3. 根據需要，可以利用這些 index 撈出對應的 name 或 age

常見的 Database 有 Cassandra, HBase, ClickHouse, Amazon Redshift, Vertica 等等

題外話: 其實 行儲存 有很多變種 (Column Family), 比如 Cassandra 其實是 Wide-Column Store, 和下面的 Document Database 有點像, 每列 可以有 不同的欄位, 但是沒有巢狀結構, 所以這邊視為 行儲存

Key-value Store

其實 NoSQL 都有 key-value pair 的資料結構, 好處是擴展性強, 寫入速度快, 但讀取 "相對 RDBMS" 慢

這邊主要是指 "儲存的格式" , 比如 SSTable

常見的 Database 有 Memcached, Redis, Amazon DynamoDB, RocksDB, LevelDB

Document-oriented Database

主要由 Document 和 Collection 構成
Document: 可以理解為 列儲存 的 列 (Record)
Collection: Documents 的集合

儲存的格式和 JSON 很像, 不過支援更多格式, 像 MongoDB 稱為 BSON (Binary JSON), 記得是 Key-Value Pair 就好
和 RDBMS 強調表間的關係不同, Document Database 不支援 RDBMS 的 JOIN, 且資料需要 Denormalize 加快存取速度
且由於是 Key-Value 儲存形式, 又沒有 ACID 的特型, 擴展性也比 RDBMS 好

舉個例子, RDBMS 可能會有下面設計 (符合 3NF)

user
| id | name  | age | id_gender |
|----|-------|-----|-----------|
| 1  | Amy   | 20  | 1         |
| 2  | Brian | 16  | 2         |
| 3  | Chloe | 18  | 1         |
| 4  | David | 22  | 2         |

gender
| id | gender |
|----|--------|
| 1  | f      |
| 2  | m      |

Document Database 則有兩種設計方法

1. Denormalization

[
    {
        "id": 1,
        "name": "Amy",
        "age": 20,
        "gender": "f"
    },
    {
        "id": 2,
        "name": "Brian",
        "age": 16,
        "gender": "m"
    },
    {
        "id": 3,
        "name": "Chloe",
        "age": 18,
        "gender": "f"
    },
    {
        "id": 4,
        "name": "David",
        "age": 22,
        "gender": "m"
    }
]

2. By reference
users collection

[
    {
        "id": 1,
        "name": "Amy",
        "age": 20,
        "id_gender": 1
    },
    {
        "id": 2,
        "name": "Brian",
        "age": 16,
        "id_gender": 2
    },
    {
        "id": 3,
        "name": "Chloe",
        "age": 18,
        "id_gender": 1
    },
    {
        "id": 4,
        "name": "David",
        "age": 22,
        "id_gender": 2
    }
]

genders collection

[
    {
        "id": 1,
        "gender": "f"
    },
    {
        "id": 2,
        "gender": "m"
    }
]

常見的有 CouchDB, MongoDB, Amazon DocumentDB, Elasticsearch (感謝留言補充)

Time-series database

Time-series Database 主要用於 Time-series 資料的存取
什麼是 Time-series 資料呢? 廣義來說, 只要帶有時間戳的資料都是 Time-series 資料

舉例來說, 我們將建立使用者的時間加上時間戳

| id | name  | age | id_gender | timestamp           |
|----|-------|-----|-----------|---------------------|
| 1  | Amy   | 20  | 1         | 2023-08-05T12:00:00 |
| 2  | Brian | 16  | 2         | 2023-08-05T12:01:00 |
| 3  | Chloe | 18  | 1         | 2023-08-05T12:02:00 |
| 4  | David | 22  | 2         | 2023-08-05T12:03:00 |

但這其實沒什麼意義, 回歸到 Database 的本質, 是為了 "業務需求" 而存在的
如果只是單純加上時間戳, 只是多了冗余的資料而已

那麼換個角度想, 時間戳可以用來做什麼?

如果是遊戲服務, 或許可以記錄使用者的活動數據, 用來檢查異常行為 (外掛, 盜號等)

activity

| user_id | activity_type | times | timestamp           |
|---------|---------------|-------|---------------------|
| 1       | login         | 1     | 2023-08-05T12:00:00 |
| 1       | click         | 5     | 2023-08-05T12:05:00 |
| 2       | login         | 1     | 2023-08-05T12:01:00 |
| 2       | purchase      | 1     | 2023-08-05T12:15:00 |
| 1       | logout        | 1     | 2023-08-05T12:30:00 |

如果是雲端服務, 或許可以定時記錄伺服器資源的用量, 搭配 Alert System 即時通知

所以嚴格來說, Time-series 資料應該要符合以下兩點

時間依賴性

採樣 (Event-based, Windowing, 有興趣請自行查閱)

等等, 這種 針對特定欄位查詢 的特性剛剛好像看過?
沒錯, Time-series Database 也可以用 行儲存!

但是相較於 行儲存, Time-series 資料通常有高頻的特性, 所以 Time-series Database 有針對 寫入 優化, 且因為會有大量的歷史資料, 所以也有壓縮 (Compression) 和 封存 (Archive) 的機制
由於 Time-series 資料多用於分析, 所以只要保住原始資料, 所有衍生的資料都可以透過 Write-Ahead Log (WAL) 重放 (Replay)

題外話: 客戶端採樣會有時區的問題, 所以多是伺服器端採樣

常見的有 InfluxDB, Prometheus