MODULE 6 · PART 1 · UNIT 1.2

兩大陣營對決:
SQL vs NoSQL

SQL 跟 NoSQL 不是「你死我活」的競爭,而是「不同場景的不同工具」。 這 Unit 把這兩個陣營背後的 CS 觀念拆給你看 — ACID、JOIN、Document Model、CAP 定理 — 以及怎麼跟 AI 一起選對工具。

§1 · SQL vs NoSQL

兩個陣營背後是兩套不同哲學

先看高層差異,再進細節 — 你才知道後面 §2-§6 在拆什麼。

概念SQL(關聯式)哲學

把資料切成多張 、表跟表之間用 id 互指、有強保證(ACID)。 為「正確性 > 彈性」而設計 — 適合「絕對不能錯」的場景。

概念NoSQL(非關聯式)哲學

把「會一起讀」的資料整坨包成一份 JSON document、結構自由、讀超快。 為「彈性 > 強保證」而設計 — 適合「結構常變、讀取量爆炸」的場景。

🆚 兩陣營高層對照
SQLNoSQL
結構
SQL
多表 + 外鍵互指
NoSQL
整坨 document(JSON)一包
查詢
SQL
JOIN 把多表拼回來
NoSQL
一個請求拿到完整資料
一致性
SQL
強保證(ACID)
NoSQL
為速度妥協(最終一致)
擴展
SQL
垂直加 CPU + 主從複製
NoSQL
水平加機器更原生
代表產品
SQL
PostgreSQL / MySQL / SQLite
NoSQL
Firestore / MongoDB / DynamoDB
適合場景
SQL
轉帳、訂單、複雜關聯
NoSQL
IG feed、聊天、巨量讀取

下面 §2-§6 把這兩個陣營背後的 CS 觀念拆開: 關聯式怎麼運作(§2)、非關聯式怎麼運作(§3)、ACID 怎麼保證(§4)、JOIN 怎麼拼(§5)、結構彈性的代價(§6)。

🔑VIBE CODER 秘訣
👀觀察
AI 預設給 Firebase / Supabase 二選一,但沒 context 它不知道你要哪個陣營 — 結果常常是「能跑、但不適合」。
💬怎麼跟 AI 講
直接報出三件事 — 結構(固定 / 常變)、一致性(絕不能錯 / 容許暫時不一致)、查詢模式(多表關聯 / 整坨讀完) — AI 才能挑對陣營。

→ 下面 §2 先進入 SQL 陣營 — 關聯式資料庫到底怎麼工作。

§2 · 關聯式模型

SQL 的世界:一堆表,用 id 互相指

上一段給了兩陣營高層比較,這段進入 SQL 陣營背後的設計 — 關聯式模型(1970 年 Codd 提出)。

概念關聯式模型(Relational Model)

SQL 的底層哲學叫「關聯式模型」。意思是:把資料切成多張 表(table),每張表只描述一種東西(用戶、訂單、商品…),表跟表之間用 id 互相指。

  • Primary Key(主鍵):每張表每筆資料的「身分證號」,例如 users.id。不能重複、不能空。
  • Foreign Key(外鍵 / FK):一張表裡指向另一張表主鍵的欄位,例如 orders.user_id 指向 users.id。資料庫會幫你檢查,被指的對象一定要存在。

這樣切表的好處:同一個用戶買 100 次,名字只存一份;商品改價,所有訂單自動拿到新價。代價是要看「小明買過什麼」必須把 3 張表「連起來」 — 這就是下一段的 JOIN

滑鼠移到中間 orders 任一筆 — 兩條 FK 箭頭會即時畫出來,指向 users 跟 products 的對應列。

users2 rows
idnameemail
u1小明a@x.com
u2小華b@x.com
orders3 rows
iduser_idproduct_idqty
o1u1p12
o2u2p11
o3u1p23
products2 rows
idnameprice
p1拿鐵120
p2可頌80
👆 滑鼠移到中間 orders 任一列,看 FK 箭頭
🔑VIBE CODER 秘訣
👀觀察
AI 為了「demo 快」可能把多種實體混塞同一張表 — 看起來能跑,但少了 FK 約束,髒資料一進來就找不到罪魁禍首。
💬怎麼跟 AI 講
檢查 AI 給的 schema:「每個實體是不是有獨立的表?」「有沒有 FOREIGN KEY 約束讓 DB 幫你守門?」 — 沒有就要求補上。

補:Normalization vs Denormalization — 重複資料是萬惡之源

概念Normalization(正規化) vs Denormalization(反正規化)

想像一張表把所有東西都塞進去 — 每筆訂單除了 order_id、quantity,還重複存著作者名字、email、商品名稱、價格。 看起來方便(一張表就拿到所有資訊),但有個大問題:同一份資料重複很多份。小明改 email,你要找出所有他的訂單一筆一筆改。漏改一筆 → 資料不一致 → bug 來了。

Normalization(正規化) 就是把重複資料拆出來:作者放 users 表、商品放 products 表、訂單只存 id 連回去。改名字只要改一個地方,所有訂單自動「看到新名字」。

但讀的時候就要 JOIN 連回去(下一段的事)— 寫得快、讀得稍慢。 反過來「為了讀快、故意重複存」叫 Denormalization(反正規化),是有意識的取捨,不是疏忽。

下面兩個按鈕讓你體感差別 — 同樣是「把小明改名」,扁平表要改 3 筆訂單;正規化表只要改 users 表的一筆。

DENORMALIZED全塞一張表
orderauthoremailproduct
o1小明ming@x.com拿鐵
o2小華hua@x.com拿鐵
o3小明ming@x.com可頌
o4小明ming@x.com拿鐵
NORMALIZED拆 users / orders / products
users
u1小明ming@x.com
u2小華hua@x.com
orders 的 author 只存 user_id → 自動看到新名字
🔑VIBE CODER 秘訣
👀觀察
AI 預設給扁平 schema(一張表全包),因為「直覺好懂、寫起來快」。但 同一個欄位被多筆共用時,改一次資料要批次更新整張表,bug 等著你。
💬怎麼跟 AI 講
每看到一個欄位都問:「這個欄位之後會被多筆 row 共用嗎?」會 → 要求 AI 拆成獨立的表,用 FK 連回去。讀的時候用 JOIN(§5)。

→ 切表的代價是要「拼回來」— §5 會講 JOIN;但 NoSQL 是相反的取捨 — §3 先看它。

§3 · 非關聯式 / Document Model

NoSQL 的世界:整坨資料用 JSON 裝在一起

跟 SQL 對立的哲學 — 不切表,整坨包成 document。作者改名 — NoSQL 要動 12 筆、SQL 只動 1 筆。

概念Document Model — 把「一起讀」的資料存在一起

NoSQL 文件式資料庫(Firestore、MongoDB)的哲學跟 SQL 相反:不切表,而是把「會一起被讀」的資料整坨包成一份 JSON 文件存起來。 要顯示一個 IG post?整筆 document 一次取出來 — 不用 JOIN、不用先抓 A 再抓 B。

優點:讀取超快、結構可以不一樣(每筆 document 自由)、新欄位直接寫進去不用 ALTER TABLE。

代價:相同資料會「重複存在多筆 document 裡」 — 每篇 post 都存著作者名字。 如果作者改名 → 你要批次更新所有他的 post。這就是 SQL(更新方便)vs NoSQL(讀取方便)的核心取捨。

posts (firestore)12 docs
{ id: "post_1", author: { name: "小明" } }
{ id: "post_2", author: { name: "小明" } }
{ id: "post_3", author: { name: "小明" } }
{ id: "post_4", author: { name: "小明" } }
{ id: "post_5", author: { name: "小明" } }
{ id: "post_6", author: { name: "小明" } }
{ id: "post_7", author: { name: "小明" } }
{ id: "post_8", author: { name: "小明" } }
{ id: "post_9", author: { name: "小明" } }
{ id: "post_10", author: { name: "小明" } }
{ id: "post_11", author: { name: "小明" } }
{ id: "post_12", author: { name: "小明" } }
未開始0/12
psql — users + posts JOIN1 user · 12 posts
// users 表(只存一份名字)
u1 小明 | ming@x.com
// posts 表(每筆只存 user_id 引用)
post_1 · user_id=u1
post_2 · user_id=u1
post_3 · user_id=u1
post_4 · user_id=u1
... 共 12 筆 posts
// JOIN 時自動拿到新 name — 不用動 posts
未開始0/1
📊 寫入次數比:NoSQL 0 vs SQL 0
🔑VIBE CODER 秘訣
👀觀察
AI 給的 NoSQL schema 為了「讀取方便」常把作者、商品等共用資料 內嵌在每筆 document。看起來巧妙,但被嵌的資料一改 → 要批次更新所有 document,做不到就資料不一致。
💬怎麼跟 AI 講
看到內嵌的子物件,問:「這份資料之後會被多筆 document 共用嗎?會被多人改嗎?」會 → 抽出來做引用(存 id),不要直接內嵌。

分散式 NoSQL 的另一個取捨 — CAP 三選二

概念CAP 定理(CAP Theorem)

當資料庫只跑在一台機器上,沒有這個問題。但只要 分散到多台(為了高可用、為了擴展),就會撞上分散式系統的鐵則 — CAP 定理

  • C — Consistency(一致性):所有節點同一時刻看到同一份資料
  • A — Availability(可用性):每個請求都能得到回應(不會 timeout 或拒絕)
  • P — Partition Tolerance(分割容忍):節點之間網路斷掉時,系統還能繼續運作

這三個 最多只能同時有兩個。實務上 P 是「現實」(網路本來就會斷),所以真正的選擇是 CP(保一致犧牲可用) 還是 AP(保可用犧牲一致)

🔺 CAP 三角 — 拖點看取捨
CConsistencyAAvailabilityPPartition Tolerance✗ 放棄
當前選擇
CA
你保留的
Consistency + Availability
你放棄的
Partition Tolerance
代表產品:單機資料庫(PostgreSQL 在一台機器上)
什麼情境:只要不分散就有 C + A — 但分散式系統「網路分割」不可避免,所以 CA 在分散式情境其實做不到。
🔑VIBE CODER 秘訣
👀觀察
AI 推「分散式 DB」時,常只說「擴展性好」,不會主動講 CAP 取捨 — 網路分割時你的系統會選 C 還是 A?這直接影響用戶體驗。
💬怎麼跟 AI 講
聽到「分散式」、「多 region」、「跨機房」這些詞,主動問:「這套系統是 CP 還是 AP?網路分割時會犧牲什麼?我的場景能接受嗎?

→ Document Model 讀超快,但失去 SQL 的兩個保證:ACID 跟 JOIN。§4 先看 ACID 是什麼。

§4 · ACID + Transaction

銀行轉帳:少了哪個字母會出什麼事?

上一段 NoSQL 為了讀取速度犧牲 ACID — 那 ACID 到底是什麼?按按鈕看四種「壞掉的轉帳」,每種對應 ACID 少了一個字母。

概念ACID — 資料庫的四個鐵保證

想像你按下「轉 $100 給朋友」 — 銀行系統要做兩件事:你的帳戶 -$100、朋友的帳戶 +$100。 如果中間出任何狀況(App 當掉、停電、餘額不夠、兩人同時轉),錢都不能憑空消失或多出來。 資料庫提供的這四個保證合起來就是 ACID

  • A — Atomicity(原子性)「要嘛全成、要嘛全廢」:不會做一半。你的帳戶扣了,朋友的帳戶就一定要加上 — 不能只做一半就停。
  • C — Consistency(一致性)「規矩永遠不能破」:銀行內建的規則(例如「餘額不能變負數」)絕對不會被破壞。
  • I — Isolation(隔離性)「兩人同時操作不會干擾」:你和你媽同一秒都在轉帳,結果跟「一個一個輪流做」要長得一樣。
  • D — Durability(持久性)「說成功就是真的成功」:App 跳出「轉帳成功」之後,就算下一秒停電也算數,不會反悔。

這四個保證打包在一起叫 Transaction(交易)。SQL 資料庫天生支援、NoSQL 看廠商支援程度。

🏦 vibe-bank.com / 轉帳系統
ATM-A
vibe-bank
ACCOUNT A
$1,000
● ready
$100
轉帳
ATM-B
vibe-bank
ACCOUNT B
$1,000
● ready
合計:$2000(應該永遠是 $2000)
// 點按鈕看 transaction log
🔑VIBE CODER 秘訣
👀觀察
AI 寫多步驟操作(轉帳、扣庫存+建訂單、刪用戶+清關聯)預設不會自己包 transaction。Demo 時看不出,真實流量裡中間 crash 一次,資料就壞了。
💬怎麼跟 AI 講
看到「要嘛同生、要嘛同死」的場景,直接問:「這段要包在 transaction 裡嗎?BEGIN / COMMIT 怎麼放?失敗 rollback 怎麼處理?

→ ACID 保住單一資料庫內的正確性,但跨表查詢還需要 JOIN — §5。

§5 · JOIN

JOIN — 把多張表拼起來

§2 把資料切多張表,這段把表拼回來 — 切換 4 種 JOIN 看「誰留下、誰被丟掉」。

概念JOIN — 把兩張表拼起來

§2 把資料拆成多張表,但實際要用時你還是要看到「誰買了什麼」 — 這就需要把表 拼起來,叫做 JOIN。 四種 JOIN 寫法的差別只在一件事:對不上的列要不要留?

下面這份資料故意設計兩個邊界 case:「小美」沒下過任何單、「舊訂單」的用戶已經被刪掉 — 切換 4 種 JOIN,你會直接看到誰被留下、誰被丟掉。

usersordersINNER JOIN
INNER JOIN只要「兩邊都對得上」的 — 對不上的整列丟掉
結果表留下 3 / 5 列
useritem這列的命運
小明拿鐵✓ 配對成功,留下
小華可頌✓ 配對成功,留下
小明美式✓ 配對成功,留下
小美NULL✗ 丟掉(users 有,沒下過訂單
NULL舊訂單(用戶已刪)✗ 丟掉(orders 有,用戶被刪了
實際 SQL 長這樣(AI 會給你這種 code)
SELECT users.name, orders.item
FROM   users
INNER JOIN orders
  ON   users.id = orders.user_id
⚠️ 選這個會漏掉什麼:小美(沒下單)+ 舊訂單(用戶已刪)都被默默丟掉。做「月活用戶」或「總營收對帳」會少算 — 而且看不到任何錯誤訊息。
🔑VIBE CODER 秘訣
👀觀察
AI 給的 NoSQL 方案常寫「先抓 users、再 for-loop 依 user_id 抓 orders」 — 這叫 N+1 query,1000 個用戶就打 1001 次資料庫,效能爆炸。
💬怎麼跟 AI 講
看到迴圈裡有查詢,問:「這段是不是 N+1?能不能用 JOIN 合成一句、或用 batch query 預載?」 — 把 query 數量明確列出來,AI 才會優化。

→ JOIN 是 SQL 的招牌;但 NoSQL 不切表,所以也沒 JOIN — 它怎麼處理結構變化?§6。

§6 · 結構彈性

加一個欄位 — SQL 5 步驟、NoSQL 直接寫

SQL 嚴格 schema 跟 NoSQL 彈性 schema 改起來代價差很多。產品快速迭代時加欄位是日常 — 方便有代價,只是「方便」被推到哪去而已。

概念Schema Migration — 改結構不是免費的

隨著產品功能長大,你常需要「給資料表加新欄位」。SQL 跟 NoSQL 對這件事的處理方式天差地遠。

SQL(嚴格 schema):必須先「宣告」這個欄位存在(ALTER TABLE),歷史資料要回填預設值。大表的 ALTER 可能 鎖表幾分鐘到幾小時 — 上線時整個 App 寫不進去。所以實務上要排時段、寫 migration script、先在測試環境量測。

NoSQL(彈性 schema):直接 db.posts.add({ ..., ar_filter: "..." }) 就好 — 新 document 有這欄、舊的沒有,DB 不管你。 看起來方便對吧?但代價來了:你的程式碼要自己處理「有的有、有的沒有」。 每讀一筆都要寫 post.ar_filter ?? "default"。debug 時你會很懷疑人生。

這就是「方便」的代價 — 不是消失,是 推給了應用層。下面兩個按鈕讓你體感差別。

SQL · 5 步驟
加 ar_filter 欄位
NoSQL · 直接寫
加 ar_filter 欄位
🔑VIBE CODER 秘訣
👀觀察
AI 給的 migration 直接 ALTER TABLE 不提鎖表時間。小表沒事,但 100 萬筆以上的大表 ALTER 可能鎖數分鐘到數小時 — 整個 App 寫不進去。
💬怎麼跟 AI 講
看到 migration 主動問:「這張表多大?ALTER 預估鎖多久?要不要排上線時段或用 online migration 工具?」 — 把規模講出來 AI 才會給對的策略。

→ 兩陣營背後的 CS 觀念都看完了 — §7 把它們套用到 5 個實際場景做選擇練習。

§7 · 場景式選型

5 題場景速測:你會直覺選哪一邊?

§1-§6 給了概念,這段把所有概念回答到 5 個具體場景 — 從 SQL / NoSQL / Key-Value 三個選項挑一個,立即知道對錯 + 為什麼。

概念先建立直覺,再學概念

選資料庫不是先看名字(PostgreSQL? Firebase?),而是先看 場景特性。 不同需求對應到不同陣營:要保證「絕不能錯」的用 SQL(關聯式);要保存「結構不固定的大量資料」的用 NoSQL(文件式);要極致速度的用 Key-Value 快取。

下面 5 題每題給你一個場景跟 3 個選項。先憑直覺答 — 答錯沒關係,答完整個 Unit 後再回來重做一次,你會發現答案變得很自然。

🏦Q1. 銀行轉帳
  • · 絕不能掉錢
  • · 兩個帳戶同步改
  • · 結構固定
📸Q2. Instagram 動態
  • · 每篇 post 結構不一
  • · 新欄位常加
  • · 巨量讀取
💬Q3. 聊天室即時訊息
  • · 訊息只增不改
  • · 需即時推送
  • · 搜尋頻率低
🛒Q4. 電商訂單系統
  • · 訂單 → 商品 → 用戶有複雜關聯
  • · 要對帳、要 JOIN
  • · 資料正確性 > 速度
🎮Q5. 多人遊戲 leaderboard
  • · 排名變動超頻繁
  • · 讀取量 >> 寫入量
  • · 結構超簡單
進度:0/5
🔑VIBE CODER 秘訣
👀觀察
選資料庫沒有「絕對的好」 — 只有「在這個場景比較適合」。AI 沒看清楚場景,預設給你最熱門的(Firebase / Supabase)。
💬怎麼跟 AI 講
看到新需求先問自己三件事:「結構固定嗎?」「多筆要同時改嗎?」「絕不能掉嗎?」三個都 yes → 跟 AI 說 SQL;結構常變、巢狀深、單筆操作 → 跟 AI 說 NoSQL;速度第一、結構超簡單 → 跟 AI 說 KV。

每個陣營有哪些代表產品 — 5 題挑挑看

概念先建立「產品 vs 場景」的對照表

知道 SQL / NoSQL / KV / Vector 四個陣營後,下一層是「每個陣營有哪些代表產品」。 你不用背特性,但要看到名字能反應出「它大概解什麼問題、適合什麼場景」。

這樣跟 AI 對話時,你聽到它推薦 Firestore,能反問「複雜查詢怎麼辦?」;它推薦 Postgres,你能反問「向量搜尋要不要直接用 pgvector?」 — 這就是「看得懂 AI 給的建議、能往下追問」的能力。

進度 0 / 5 · 答對 0
Q1

你要做一個轉帳系統,需要 ACID 保證、強一致性。AI 應該推薦哪個?

💳 Bank App✓ Synced
*.4521 儲蓄
*.8763 王小明
金額NT$ 1,000
✅ 成功 #TX25038,420 → 7,420
Q2

你要做即時協作聊天 App,訊息要「資料變了 client 自動收到」。AI 預設會推哪個?

💬 設計組 #general● 5 在線
alex 收到~下午 3 點✓✓
mia +1 我準時
alex 正在輸入...
Q3

你要做一個 AI 客服 + RAG 語意搜尋,剛起步、規模小。AI 應該推哪個?

🤖 AI 客服
你:退貨流程要多久?
AI:收到貨後 7 個工作天會退款到原付款方式。
📎 來源:退貨政策 v3.2 · FAQ #18相似度 0.92 · 0.87
Q4

你要做 API 限流(每個 user 每分鐘最多 100 次),計數要超快。AI 推哪個?

⚡ /api/search1m window
user_4521▓▓▓▓▓▓▓▓░░87/100
user_9988▓▓▓▓▓▓▓▓▓▓100/100
user_3310▓▓░░░░░░░░18/100
⚠ user_9988 → 429 Too Many Requests
Q5

你是 vibe coder,想要 PostgreSQL 的所有能力 + 不想自己架 server + 還要附 Auth。AI 推哪個?

⚡ Supabase Dashboard
📊 Tables12
👤 auth.users142
📦 orders1.2k
🔑 OAuthGoogle ✓ GitHub ✓
postgres://...supabase.co
🔑VIBE CODER 秘訣
👀觀察
AI 沒 context 預設給 Firebase / Supabase 二選一 — 對 80% 的小專案剛好,但對你那 20% 特殊場景可能完全不對(高並發、向量搜尋、強一致需求)。
💬怎麼跟 AI 講
給 AI 推薦時把 5 件事描述清楚:流量規模、結構複雜度、是否需要 ACID、是否需要向量搜尋、團隊規模。然後說:「列 2–3 個選項並比較」 — 強迫權衡。

→ 最後看 AI 時代最常見的後端架構 — §8。

§8 · AI App 後端

想做一個 ChatGPT 類產品?這是資料庫該有的樣子

從第一個需求開始,看著資料模型一個個長出來 — 跟 AI 講需求的人 vs 跟 AI 拷貝範例的人,差距在這。

概念跟著需求長 schema — AI App 後端的標準成形路徑

ChatGPT 類產品千變萬化,但後端資料模型有 80% 共通的長相 — 不是巧合,是「需求一個個加上去,自然會逼出這幾張表」。 下面用一個 vibe coder 的開發直播帶你跑一遍 — 每加一個需求,就有一個資料模型解問題。 看完你就明白:這不是「規格清單」,是「逼到牆角後的自然解」。

📈需求演進 — 每加一個需求,自然冒出一張表
用戶問 AI 一個問題、AI 回答
2conversations3messages
對話跟訊息是 1:N — 拆開兩張表才能左邊 sidebar 列出歷史對話。
用戶要看自己的歷史、要付費才能用 GPT-4
1users
帳號、付費方案、配額會被多個對話共用 — 不能塞在 conversations 裡。
AI 要能讀我上傳的文件、做 RAG 檢索
6files4embeddings
檔案幾 MB 不能放 DB;向量需要的索引(HNSW / IVF)跟 B-tree 完全不同,要分開存。
不能被免費用戶灌爆 token、要擋濫用
5rate_limits
每秒可能寫上萬次 — 放 PostgreSQL 會把主庫鎖到變慢;用 Redis 純記憶體 counter 才扛得住。
畫面 → 後端對照圖
數字對應下方卡片
2Chats
Schema 設計
向量搜尋
Vibe coding
GPT-4
542/100
1
pgvector 跟 Pinecone 怎麼選?
小規模用 pgvector 一張表搞定,相似度搜尋用 cosine...
3messages·4向量檢索
6📎
Message ChatGPT...
儲存色系:SQLVector DBRedisS3
概念6 個表 · 4 種儲存 — 這就叫 polyglot persistence

看出來了嗎?6 個表分別住在 4 種儲存(SQL / Vector / Redis / S3) — 不是設計師耍帥,是 每種需求都有最匹配的工具。 工程界叫這個 polyglot persistence(多語言持久化)。但你不需要記名詞,只要記住一句話:單一資料庫不可能滿足所有需求

下次跟 AI 講「幫我做一個 ChatGPT clone」,不要等 AI 給你方案 — 你 主動帶出這 4 個需求,問:
➀「對話跟訊息要分開兩張表,對嗎?」
➁「embeddings 第一天就用 pgvector 還是先用 jsonb 欄位?」
➂「rate limit 走 Redis 還是 PostgreSQL?」
➃「檔案放 S3,DB 只存 metadata,對嗎?」
四題答完,AI 給你的方案會精準到 可以直接動手寫

1
👤users
PostgreSQL
畫面對應:右上角頭像、剩餘額度
為什麼這個儲存:標準關聯式 — 帳號、付費方案、使用配額
id (PK)emailplancreditscreated_at
2
💬conversations
PostgreSQL
畫面對應:左側 sidebar 的 chat 清單
為什麼這個儲存:一個用戶的每個 chat session — 用 FK 連回 users
id (PK)user_id (FK)titlemodelcreated_at
3
📝messages
PostgreSQL(append-only)
畫面對應:中間訊息泡泡(user / assistant)
為什麼這個儲存:量大、只寫不改、按時序讀 — 經典的 append-only log
id (PK)conversation_id (FK)rolecontenttokenscreated_at
4
🧬embeddings
pgvector / Pinecone
畫面對應:「找之前提過的內容」、RAG 檢索
為什麼這個儲存:向量相似度搜尋 — 不是用 = 找,是用「最近」找
idmessage_id (FK)vector[1536]
5
🚦rate_limits
Redis(in-memory)
畫面對應:「You've reached your limit」提示
為什麼這個儲存:每次請求都要 +1 — 不能拖累主 DB
user_id : count : window
6
📦files
S3 / R2 + DB metadata
畫面對應:拖檔上傳、附件縮圖
為什麼這個儲存:檔案本身放物件儲存,路徑 + 權限放 DB
iduser_id (FK)s3_keysizemime_type
🔑VIBE CODER 秘訣
👀觀察
AI 預設給你「一張 messages 表吃全部」 — 簡單,但加上 RAG、加上 rate limit、加上付費方案那一刻全爆。或者它直接推 Pinecone + Firebase + R2 一整套,小規模太重、帳單炸鍋。
💬怎麼跟 AI 講
講需求要分階段 — 先講「MVP 最小架構」,再講「規模化後要拆什麼」。AI 自然會給你「先一張 messages 表 + pgvector,後續再 split」的演進路徑,而不是一上來就全套服務。

→ 走完 8 段,你已經有 vibe coder 跟 AI 對話的全套後端直覺。§9 收尾把整個 Unit 收口。

§9 · 收尾

這個 Unit 你帶走了什麼

SQL vs NoSQL 不是「哪個比較好」,
是「在這個場景哪個比較適合」。

跟 AI 討論架構時可以直接用的 7 個直覺:

  • · 轉帳場景 → 想到 ACID、Transaction、SQL
  • · 資料有複雜關聯 → 想到 JOIN、想到關聯式
  • · 巢狀資料、結構常變 → 想到 Document Model、想到 NoSQL
  • · 看到「先抓再抓」 → 想到 JOIN,問能不能合成一句
  • · 看到「加欄位」 → 評估遷移代價,考慮 jsonb 欄位
  • · 分散式 DB → 想到 CAP,問放棄了什麼
  • · AI App 後端 → users / conversations / messages / embeddings / rate_limits / files 六件套
📍 接下來
Part 2 預告:資料模型設計 — Schema 是 vibe coder 的劇本

知道選哪個陣營之後,下一步是學會「畫出你的 App 的資料地圖」 — 怎麼跟 AI 一起把 schema 設計好,少踩遷移地獄。