MongoDB Glossary

MongoDB 核心概念與術語參考。

RDBMS vs MongoDB

  flowchart LR
    subgraph RDBMS
        subgraph SQL_Database[SQL Database]
            subgraph Tables
                subgraph Rows
                    subgraph Columns
                    end
                end
            end
        end
    end

    subgraph MongoDB
        subgraph NoSQL_Database[NoSQL Database]
            subgraph Collection
                subgraph Documents
                    subgraph Fields
                    end
                end
            end
        end
    end

    Tables <-->|vs| Collection
    Rows <-->|vs| Documents
    Columns <-->|vs| Fields
RDBMSMongoDB
DatabaseDatabase
TableCollection
RowDocument
ColumnField
IndexIndex
JOIN$lookup / Embedded Document

Schema Design Patterns

核心原則: 一起存取的資料應該一起儲存(Data that is accessed together should be stored together)

Inheritance Pattern

將不同類型但有共同屬性的資料存放在同一 Collection,透過 product_type 欄位區分:

  classDiagram
    class Books {
        title
        author
        publisher
    }

    class eBook {
        title
        author
        publisher
        product_type: "ebook"
    }

    class printedBook {
        title
        author
        publisher
        product_type: "printed"
    }

    class audioBook {
        title
        author
        publisher
        product_type: "audio"
    }

    Books <|-- eBook
    Books <|-- printedBook
    Books <|-- audioBook

其他常見 Pattern

Pattern說明適用場景
Computed Pattern預先計算並儲存結果頻繁讀取的聚合結果
Approximation Pattern儲存近似值而非精確值計數器、統計資料
Extended Reference Pattern嵌入常用欄位的副本減少 $lookup 查詢
Schema Versioning Pattern文件包含 schema 版本漸進式 schema 演進

Document Design 實例:遊戲角色系統

透過 RPG 遊戲角色系統,比較 RDBMS 與 MongoDB 的設計差異。

RDBMS 正規化設計

  erDiagram
    players ||--o{ characters : has
    characters ||--o{ inventory : has
    inventory }o--|| items : references
    characters ||--o{ character_skills : has
    character_skills }o--|| skills : references

    players {
        int player_id PK
        string username
        string email
        datetime created_at
    }

    characters {
        int character_id PK
        int player_id FK
        string name
        string class
        int level
        int hp
        int mp
    }

    items {
        int item_id PK
        string name
        string type
        int base_damage
    }

    inventory {
        int inventory_id PK
        int character_id FK
        int item_id FK
        int quantity
    }

    skills {
        int skill_id PK
        string name
        int mana_cost
    }

    character_skills {
        int character_id FK
        int skill_id FK
        int skill_level
    }

特點:

  • 6 個表,透過 Foreign Key 關聯
  • 查詢角色完整資訊需要多次 JOIN
  • 修改 item 基本資料只需更新一處

MongoDB 文件設計

{
  "_id": ObjectId("..."),
  "username": "player123",
  "email": "player@example.com",
  "created_at": ISODate("2024-01-15"),
  "characters": [
    {
      "character_id": "char_001",
      "name": "DragonSlayer",
      "class": "Warrior",
      "level": 42,
      "stats": {
        "hp": 1500,
        "mp": 200,
        "strength": 85,
        "agility": 45
      },
      "inventory": [
        {
          "item_id": "sword_001",
          "name": "Flame Sword",
          "type": "weapon",
          "damage": 150,
          "quantity": 1,
          "equipped": true
        },
        {
          "item_id": "potion_001",
          "name": "Health Potion",
          "type": "consumable",
          "effect": "+500 HP",
          "quantity": 10
        }
      ],
      "skills": [
        {
          "skill_id": "skill_001",
          "name": "Flame Strike",
          "level": 5,
          "mana_cost": 50
        }
      ]
    }
  ]
}

特點:

  • 1 個 Document 包含所有相關資料
  • 查詢角色完整資訊只需一次讀取
  • 適合「讀取時需要完整資料」的場景

設計比較

面向RDBMSMongoDB
資料結構多表 + Foreign Key單一 Document 嵌入
查詢完整角色多次 JOIN單次讀取
更新物品基本資料更新一處即可需更新所有嵌入的副本
新增欄位需 ALTER TABLE直接新增,無需 schema 變更
交易一致性原生 ACID單文件原子性,多文件需交易
適用場景資料關聯複雜、需頻繁更新讀取為主、資料常一起存取

設計決策指南

何時使用嵌入(Embedding):

  • 資料通常一起讀取
  • 子資料生命週期依賴父資料
  • 子資料數量有限且不會無限增長

何時使用引用(Reference):

  • 子資料獨立於父資料存在
  • 子資料數量可能很大
  • 需要獨立查詢子資料

Transaction

MongoDB 支援多文件 ACID 交易(4.0+)。

Read Concern

控制讀取操作返回的資料一致性層級:

Level說明
local返回本地最新資料(預設)
available類似 local,用於 sharded cluster
majority返回已被多數節點確認的資料
linearizable返回反映所有成功寫入的資料
snapshot返回交易開始時的快照

Write Concern

控制寫入操作的確認層級:

Level說明
w: 1主節點確認(預設)
w: "majority"多數節點確認
w: <number>指定數量節點確認
j: true寫入 journal 後確認

Read Preference

控制從哪個節點讀取資料:

Mode說明
primary只從主節點讀取(預設)
primaryPreferred優先主節點,不可用時讀取次要節點
secondary只從次要節點讀取
secondaryPreferred優先次要節點
nearest從網路延遲最低的節點讀取

Replica Set

MongoDB 的高可用性機制,由多個 mongod 實例組成。

節點類型

類型說明
Primary接收所有寫入操作
Secondary複製 Primary 的資料,可處理讀取
Arbiter僅參與投票,不儲存資料

Explain(執行計畫分析)

SQL 資料庫的執行計劃分析,請參考 SQL Explain

使用 explain() 分析查詢效能:

db.collection.find({ ... }).explain("executionStats")

queryPlanner 欄位說明

欄位說明
namespace查詢的集合
indexFilterSet是否使用索引
parsedQuery解析後的查詢條件
winningPlan最佳執行計劃
rejectedPlans被拒絕的執行計劃

executionStats 欄位說明

欄位說明
executionSuccess是否執行成功
nReturned返回的文件數
executionTimeMillis執行時間(毫秒)
totalKeysExamined索引掃描次數
totalDocsExamined文件掃描次數

Stage 類型

Stage說明效能
COLLSCAN全表掃描⚠️ 避免
IXSCAN索引掃描✅ 建議
FETCH根據索引檢索文件✅ 正常
IDHACK_id 查詢的優化✅ 最佳
SORT記憶體排序⚠️ 考慮加索引
LIMIT限制返回數量✅ 正常
SKIP跳過文件⚠️ 大量 skip 效能差
SHARD_MERGE合併分片結果✅ 正常
COUNT_SCAN使用索引計數✅ 建議
COUNTSCAN不使用索引計數⚠️ 避免
TEXT全文索引查詢✅ 正常
PROJECTION欄位投影✅ 正常

應避免的 Stage

以下 Stage 出現時應考慮優化:

  1. COLLSCAN - 全表掃描,應建立索引
  2. SORT - 記憶體排序,應建立複合索引
  3. SUBPLA - 未使用索引的 $or 查詢
  4. COUNTSCAN - 不使用索引的 count
  5. 大量 SKIP - 考慮使用 range query 替代

Explain 輸出範例

{
  "explainVersion": "1",
  "stages": [
    {
      "$cursor": {
        "queryPlanner": {
          "namespace": "demo.sop",
          "parsedQuery": { "_id": { "$eq": "951753" } },
          "winningPlan": { "stage": "IDHACK" }
        },
        "executionStats": {
          "executionSuccess": true,
          "nReturned": 1,
          "executionTimeMillis": 0,
          "totalKeysExamined": 1,
          "totalDocsExamined": 1
        }
      }
    },
    {
      "$lookup": {
        "from": "sop_acl",
        "as": "acl_data",
        "localField": "_id",
        "foreignField": "sop_id",
        "totalDocsExamined": 4,
        "collectionScans": 1,
        "indexesUsed": []
      }
    }
  ]
}

上例中 $lookup 階段的 collectionScans: 1 表示對 sop_acl 進行了全表掃描,應考慮在 sop_id 欄位建立索引。


Aggregation Pipeline

聚合管線是 MongoDB 進行資料分析的核心功能,類似 SQL 的 GROUP BY

常用階段

詳見 MongoDB CLI - Aggregation Pipeline


MongoDB Compass

MongoDB 官方的 GUI 工具,提供:

  • 視覺化查詢建構
  • Schema 分析
  • 效能監控
  • 索引管理
  • Aggregation Pipeline 建構器

相關主題