MODULE 6 · PART 1 · UNIT 1.1

什麼是資料庫?
為什麼 AI 時代更需要懂它?

AI 能幫你寫程式,但不會主動幫你想「這份資料活在哪一層」。 這 Unit 從 CS 角度拆給你看 — 資料庫到底在解什麼問題、為什麼非它不可、跟 AI 講需求時你要提供哪些 context。

§1 · 資料庫概念

什麼是資料庫?

不是資料夾、不是 Google Sheets — 而是為「跨重整、跨裝置、跨用戶共享」而存在的儲存系統。

概念資料庫到底是什麼 — 一句話定義

資料庫不是「比較厲害的檔案」,也不是「線上版 Excel」。 它存在的理由很單純 — 讓資料活過程式的生命週期、讓不同裝置的不同人讀到同一份

這聽起來很抽象。但拆開來看,它做的就是 四件事:把資料的形狀守住(結構化)、找得快(高效查詢)、多人同時動不打架(並發控制)、斷電後還活著(持久化)。這四件事缺一個,都不能叫資料庫。

下面分三步把這件事吃進去: 先看「跨裝置共享」實際長什麼樣 → 再定位資料庫在整個系統裡的「居住階層」 → 最後一關一關拆它做的四件事。

步驟 1先看:跨裝置共享是什麼意思

同一個 App 同時開在筆電跟手機上 — 兩台裝置各有一個 Volatile(活在記憶體)跟一個 Persistent(活在資料庫)計數器。試試看:哪個計數器會跨裝置同步、哪個重整就歸零。

📱 vibe-counter.com — 同一個 App 在兩台裝置
vibe-counter.com
💻
VOLATILE
Volatile · useState
0
PERSISTENT
Persistent · DB
0
🏛️ 後端 DB
0
共享狀態
9:41
vibe-counter.com · 📱
VOLATILE
Volatile · useState
0
PERSISTENT
Persistent · DB
0
VOLATILE— 各自獨立、重整歸零
PERSISTENT— 兩台裝置即時同步、撐過重整

步驟 2資料居住的 5 階

資料庫住在整條「記憶體階層」的最下面。愈往上愈快但愈短命、愈個人;愈往下愈慢但愈持久、愈能共用。「該存哪」其實就是在問「該住哪一階」 — 而資料庫就是最下、最慢、但最持久、最共享的那一階。

愈往下:
愈慢、愈大、愈持久、愈多人能共用
愈往上:
愈快、愈小、愈短命、愈個人

步驟 3資料庫做的四件事(§2-§5 各拆一件)

資料庫之所以叫資料庫,是因為它同時把這四件事內建好 — 結構化高效查詢並發控制持久化。下面四關,看 AI 推給你的方案到底漏了哪一個契約。

0 / 4
1 / 4 關做會員系統,AI 推 JSON 檔
👤
你 / 咨詢者
我要做一個會員系統,要存使用者資料。AI 朋友叫我直接用 JSON 檔就好,這樣對嗎?
🤖
AI 助手
對啊超簡單!把使用者通通塞進 users.json 的陣列,新增就 push、修改就直接改 object — 不用學什麼資料庫,前端後端讀同一個檔,省事。
// users.json
[
  { "name": "Ada", "age": 30 },
  { "name": "Bob", "age": "二十" }   // ← 誰也擋不住
]
⚠️ AI 這個方案漏了哪個契約?
🔑VIBE CODER 秘訣
👀觀察
資料庫做的四件事 — 結構、查詢、並發、持久 — 是「資料庫之所以叫資料庫」的本質。 但 AI 預設不會幫你想這四件事,它只給你「現在能跑」的最小方案:volatile state、in-memory Map、JSON 陣列。Demo 過得了,產品撐不住。
💬怎麼跟 AI 講
跟 AI 講資料需求時,先回答這四題:「資料形狀有哪些規則(schema)?」「哪些欄位常被查(index)?」「有沒有多人同時動同一筆的場景(並發)?」「斷電 / 重新 deploy 不能掉(持久化)?」 — 把這四題答好給 AI,它的方案才會從 demo 等級升到產品等級。

→ 下面 §2 先從第一個契約「結構化」開始 — 它是讓資料庫從一堆檔案變成「可信來源」的第一道門。

§2 · 結構化 = Schema 是資料的結構

Schema 是資料的結構

上一段預告了四個契約,這段拆第一個 — 結構化。同樣一筆髒資料丟進 NoSQL 倉庫 vs SQL 守門,結果差很多。

概念Schema(綱要) — 預先寫死的資料規則

你用 AI 做註冊頁時,前端會擋 email 沒 @、年齡填中文、密碼太短 — 但前端可以被繞過,AI agent、webhook、後台腳本都可能直接寫到資料庫。Schema 就是把同一套規則寫進資料庫本身,所有寫入路徑都被同一份規則檢查,不合規的當下擋下。

你跟 AI 講的話 · 白話需求prompt
做一個 users 表:
- 每個人一定要有名字
- 年齡要是數字
- email 要長得像 email
- 價格不能是負的
AI 幫你生的 schema · 資料庫約束auto-generated
CREATE TABLE users (
  name  TEXT    NOT NULL,          -- 一定要有名字
  age   INTEGER,                   -- 數字
  email TEXT    CHECK (email~'@'), -- email 格式
  price NUMERIC CHECK (price >= 0) -- 不能負
);

怎麼用:跟 AI 描述五種規則就夠 — 必填型別格式範圍外鍵 / 唯一。AI 自動翻成 CREATE TABLE 的約束。 NoSQL 沒這層 — 什麼都收,等你讀資料才發現一半對不上。

實驗:同一筆髒資料 → NoSQL vs SQL 反應
📦NoSQL 倉庫來者不拒收下 0
📭倉庫空空 — 按上方按鈕投入資料
🛡️SQL 守門寫入時擋下0·0
🛡️守門待命 — 按上方按鈕嘗試寫入
Schema 工具箱 · 點擊看 SQL 語法
寫 schema 的成本
10 分鐘設好 5 個 constraint
髒資料連 prod 都進不去
不寫 schema 的成本
半年後 debug 3 小時
前端炸 → 翻日誌 → 寫 migration → 洗資料
🔑VIBE CODER 秘訣
👀觀察
AI 給的 schema 常常型別寫了、必填漏了,或 FK 沒設定 — 看起來能跑,髒資料一進來就 debug 三小時。
💬怎麼跟 AI 講
每次拿到 schema 都用 5 件事 checklist 過一遍:「型別對嗎?哪些必填?預設值是什麼?有沒有範圍約束?FK 有沒有指對?」漏一項都讓 AI 補上。

→ Schema 守住資料的形狀,但 100 萬筆裡找一筆還是慢 — 這是 §3 要解決的問題。

§3 · 高效查詢 = Index 是什麼

Index 不是魔法 — 它是用「事先排好 / 建好對照表」換查詢速度。

上一段守住資料形狀,這段要解決『找得快』。同一筆查詢,O(n) vs O(log n) vs O(1)。

概念Index(索引) — 就像書的目錄

想像一本厚厚的字典,但沒有目錄 — 要找「資料庫」這個詞,只能從第一頁翻到最後一頁。100 頁還好,100 萬頁就崩潰。 這叫 full table scan(全表掃描),資料量愈大花的時間愈久 — 工程師會說「複雜度是 O(n)」,意思就是「跟資料量 n 成正比」。

Index(索引) 就是幫某個欄位多做一份「目錄」。最常見的是 B-tree(像一棵排好順序的樹),查詢時間變成 O(log n) — 100 萬筆也只要約 20 步就找到。 還有更快的 hash 索引,等於建一張對照表,O(1) 直接拿到(不管多大筆,固定時間)。

⬇️ 按 GO 看三種方法同時找同一個 id — 誰先到?
資料量 1,000 筆,找 id = 182
O(n)📖 一頁頁翻
Full table scan
0/ 1000
O(log n)🌳 對折砍半
B-tree index
0[0, 999]
O(1)🗂️ 對照表
Hash index
key=182bucket 82
0/ 1 次到位

但 index 不是免費的:每加一個 index,寫入會變慢(要同步更新目錄)、硬碟要多吃一份空間。所以哪些欄位該下、哪些不該下,是真實的工程取捨。 下面是真的 JavaScript benchmark — 同一筆 id 查 100 萬筆資料,三種方法的時間差會直接打在你眼前。

資料量:
目標 id:(0 ~ 99,999
O(n)
Full table scan
沒下 index — 從頭翻到尾
O(log n)
B-tree index
事先排序 — 二分搜尋
O(1)
Hash index
建一張對照表 — 直接拿
Index 不是免費的
+ 讀取超快
指定欄位的查詢加速
寫入變慢
每次寫入要同步維護 index
多吃硬碟
每個 index 都是一份額外資料
🔑VIBE CODER 秘訣
👀觀察
AI 預設不下 index — 它不知道你會怎麼查。Demo 時看不出差,資料量長到 10 萬筆才開始卡。
💬怎麼跟 AI 講
查詢變慢時不要說「優化效能」(太模糊),直接說:「幫我列出哪幾個欄位最常被當 WHERE 條件查,要不要下 index」 — 把選擇權還給 AI 但給它需要的資訊。

→ 找得快了,但同一筆資料兩個人同時要改怎麼辦?— §4 並發控制。

§4 · 並發控制

兩個用戶同時下單 — 庫存會少賣嗎?

資料的正確性除了形狀,還有『多人同時動』。切換 3 種寫法,看哪一邊會出包。

概念Race Condition(競爭條件) — 多人同時動同一筆資料

想像庫存還剩 10 件。用戶 A用戶 B 幾乎同時按下「購買」:程式先「讀」出庫存 = 10、計算「10 - 1 = 9」、再「寫回」9。 如果 A 跟 B 同時跑這三步、互不知道對方,兩人都會讀到 10、都寫回 9 — 結果應該賣兩件、庫存應該變 8,卻變成 9。少賣了一件。這就是 race condition:誰先誰後沒人管,結果取決於 OS 排程的運氣。

資料庫提供兩種解法:Transaction(交易)BEGIN / COMMIT 包成「不可被打斷」的單位,資料庫鎖住那一列,A 處理完才換 B。Atomic operation(原子操作) 更直接 — 根本不抓資料,直接告訴 DB UPDATE stock = stock - 1,DB 內部保證這個運算不可分割。

📱 vibe-shop.com / iPhone 15 Pro
📱
iPhone 15 Pro
256GB · 鈦原色
NT$ 36,900
庫存
10
下單次數
0
實際扣庫存
0
少賣(漏單)
0
⏱ 執行時序圖0 events
AB(點左邊購買按鈕看時序)
RW○ race 風險區
🔑VIBE CODER 秘訣
👀觀察
AI 寫的「先 SELECT 抓出來、改一改、再 UPDATE 回去」三步式邏輯,在庫存、餘額、按讚數這類場景,一個人用對、多人用就會少賣
💬怎麼跟 AI 講
看到三步式寫法,問:「這段有沒有並發風險?要包 transaction 還是改 atomic update?」明示你關心多人同時操作的情況。

→ 結構、查詢、並發都做了,但機器一斷電全沒了 — §5 持久化。

§5 · 持久化 = Durability

拔電源那一瞬間 — 誰活下來?

最後一個契約 — 寫進去之後真的活著。4 台機器排在你面前,寫入、拔電源、看誰活下來。

概念Durability(持久性) — 「寫進去了」其實有等級之分

你以為「資料寫進去了」就安全?其實沒這麼簡單。資料從程式出發到「真的躺在硬碟上」,中間還會在作業系統的「暫存區」停留一下 — 為了效能,OS 通常會延後寫入。 這個空窗期斷電 → 資料消失。

所以資料庫多了兩道保險:fsync 命令 OS「現在馬上把資料寫到硬碟,不准延後」;WAL(Write-Ahead Log) 先寫一份「我要做什麼」的日誌、強制落地,再去動真正的資料表 — crash 後可以照日誌重做一次。

但單機再可靠也擋不住整台機器掛掉。所以還有 Replication(複製) — 同一份資料同步到第二台、甚至放到別的機房。主庫掛了從庫頂上,這就是「高可用」的基本招式。

DISK
1
ram
🧠
程式記憶體
useState · 變數
(空)
斷電瞬間就消失
2
browser
💻
瀏覽器本機
localStorage · IndexedDB
(空)
綁這台機器、這個瀏覽器
3
db
🏛️
主庫
PostgreSQL Primary
(空)
fsync 完才算落地
4
replica
🛡️
從庫副本
Read Replica · 異地
(空)
主庫掛了我頂上
(按「寫入一筆資料」開始 → 然後試「拔電源」看誰活下來)
關鍵字
fsync · 強迫資料從 page cache 真的寫到硬碟 — 不呼叫,斷電就掉
WAL · Write-Ahead Log,先寫日誌再改本體,crash 後可重放
Replication · 多副本同步,主庫掛了從庫頂上
🔑VIBE CODER 秘訣
👀觀察
AI 講「存起來了」很模糊 — 可能是程式記憶體、瀏覽器、後端、有沒有副本都不清楚。出事才發現存在最弱那層。
💬怎麼跟 AI 講
三連問:「存哪一層?」「有沒有副本(replica)?」「備份多久跑一次,能還原到哪一刻?」 — 這三題答完,你才知道資料的真實保護等級。

→ 這四個契約讓 App 不掉資料、不出包 — 但這還只是「技術價值」。下面 §6 要講「商業價值」:為什麼資料庫是 vibe coder 的護城河。

§6 · 商業護城河

AI 能複製 UI,但拿不走累積的資料

四契約解決『不出事』;接下來講『為什麼出事不只是 bug、是商業災難』。

概念Data Moat(資料護城河) — 累積即護城河

AI 時代介面是廉價的 — Instagram、Netflix、Spotify 的 UI,AI 看一眼就能仿。那為什麼大家不換家?因為真正貴的東西在資料庫裡:追蹤的 800 個朋友、看過哪些影片到第幾分鐘、失戀那週狂播哪首歌 — 新平台抄不走也補不回來

對 vibe coder 的啟示:跟 AI 設計 schema 時主動加一句「哪些欄位之後會變值錢?用戶行為、互動記錄、偏好歷史,第一天就要存」— 護城河是滴水穿石的,不能事後補。

📸Instagram
UI 可抄 90% · 資料可抄 5% · 落差 85pp
看得見 · UI90%

九宮格照片牆、限動圓圈、底部導覽 — 看一眼就知道怎麼排

看不見 · 你的朋友圈5%

~ 2,000 億條好友關係追蹤的 800 個人、五年來按過讚的每張照片、跟誰常互傳訊息 — 換到新 App,朋友全不在那邊,你還要不要用?

🔑VIBE CODER 秘訣
👀觀察
AI 給的 schema 只滿足「現在的功能需求」,不會主動幫你留下「未來變值錢」的欄位。半年後想做個人化推薦,才發現歷史資料根本沒存。
💬怎麼跟 AI 講
schema 設計階段主動問:「哪些欄位之後會變值錢?用戶行為、互動歷史、偏好變化要不要從第一天就存?」 — 護城河是日積月累的,不能事後補。

→ 資料庫是護城河,但選錯一樣會把護城河變沼澤 — §7 怎麼選。

§7 · 場景化選型

不要先問 AI 選什麼 — 先找到「最像你」的場景

知道資料庫多重要之後,下一步:怎麼選對。點下面 3 個 App 看哪個最像你的,再直接複製它的 prompt 去問 AI。

概念場景化選型:類比 > 規格表

AI 沒給 context 時預設給你 Firebase / Supabase — 因為它不知道你的需求是哪一型。 但其實 90% 的個人 App 都長得像下面 3 種之一: 自己用的工具型 App有金流的交易型 App讀重型的社群 App

找到最像你的場景,直接複製它的 prompt 去問 AI — 比起硬填一張問卷,這樣的 context 更具體,AI 也更知道你在哪個權衡點上。

⚡ 即將售完
點我看拆解 →
🔑VIBE CODER 秘訣
👀觀察
沒給 context 直接問 AI「推薦資料庫」,多半預設 Firebase / Supabase — 可能對也可能完全不對。它只是猜你「最有可能」的場景。
💬怎麼跟 AI 講
先找到上面最像你的 App 場景,把它的 prompt 複製給 AI,並加一句:「列 2–3 個選項、比較優缺點,特別說明擴展性與遷移成本」 — 強迫它幫你權衡,不是直接推薦。

→ 選型不只看現在,還要看「半年後」— §8。

§8 · 半年後才會爆的事

AI 不會主動警告你的事 — 規劃時就要想到

選對只是第一關,第二關是『半年後流量長 10 倍』。拖時間軸看不同階段會冒出什麼問題 — 每個都是「前期決策」種下的。

概念Technical Debt(技術債) 與 Scaling Cliff(擴展懸崖)

軟體工程裡有個現象:很多 demo 時跑得好好的方案,到了真實流量會「突然」爆 — 但其實不是突然,是 前期決策埋下的債 在累積到某個臨界點才出事。

這條軸把它拆成 4 個階段。每個階段會冒出特定型態的問題 — 查詢慢、並發 bug、帳單炸鍋、遷移地獄、廠商鎖死、跨區法規。 AI 在你問「現在能不能跑」時不會主動講這些 — 因為「未來」不在它的視野裡。

📅 產品時間軸 — 拖滑桿看每個階段
Demo第 1 週100 用戶第 1 個月10k 用戶第 6 個月1M 用戶第 1 ~ 2 年
Demo< 10 用戶第 1 週
你 + 朋友幾個人試玩
暫時沒事 — 但前期的選擇正在累積
🔑VIBE CODER 秘訣
👀觀察
AI 給的方案只解「現在能不能跑」 — 半年後爆的事不在它的視野裡。Demo OK 不等於可上線、可上線不等於可規模化。
💬怎麼跟 AI 講
規劃時固定問兩題:「半年後 10× 流量還跑得動嗎?瓶頸會在哪?」「如果想換廠商或換 DB,遷移成本多痛?」 — 強迫 AI 看長期。

→ 契約、商業、選型、風險都看完,最後回頭看「並不是所有資料都該丟資料庫」— §9。

§9 · State Locality

跟 AI 講需求前 — 把每份資料分到對的桶

這個 Unit 走完前的最後一個本能 — 下需求前先分桶。拖卡片到三個桶,放完按「看正解」會告訴你為什麼 + AI 會怎麼猜。

概念State Locality(狀態定位) — 每份資料屬於哪一層

做產品時,所有資料都可以歸到三個位置:

  • UI State(React useState 等):只活在「這個瀏覽器、這次開啟」,重整就消失。適合純畫面狀態。
  • 瀏覽器本機(localStorage / IndexedDB):跨重整還在,但綁這台機器、這個瀏覽器,沒辦法跨裝置同步。適合個人偏好。
  • 後端資料庫:所有裝置、所有用戶都能讀到同一份資料,能備份、能稽核。商業資產都在這。

分錯桶會發生具體災難 — 把訂單放 useState(重整就棄單)、把搜尋記憶放資料庫(每筆都打 server)。 AI 在沒有 context 的情況下「預設往最簡單的那層猜」,所以你要在心裡先有答案 — 拖完卡片後會看到每張卡片的正解、丟錯的具體災難,以及 AI 通常會猜哪邊。

候選卡片(拖到下面三個桶;無法拖也可點任一桶的「放這」按鈕)
頁面滾動位置
純 UI
正在輸入到一半的留言
未送出
深色模式(單機)
個人偏好
搜尋條件記憶
回來還在
通知開關(要跨裝置)
跨裝置同步
使用者大頭照
商業資產
電商訂單
商業核心
稽核日誌
合規
UI StateReact useState · 暫態
拖卡片進來
瀏覽器本機localStorage · 單裝置
拖卡片進來
後端資料庫PostgreSQL · 共享
拖卡片進來
🔑VIBE CODER 秘訣
👀觀察
沒給線索,AI 預設把每份資料丟到最簡單那層(state)。Demo 階段看不出問題,上線後用戶換裝置、重整、跨用戶共享時才爆。
💬怎麼跟 AI 講
講需求時主動標明每份資料的桶:「會員偏好要跨裝置同步 → 放 DB」「未送出草稿 → state 就好」「搜尋條件記憶 → localStorage」 — 把分桶結論直接給 AI。

→ 分完桶你才知道哪些丟資料庫、哪些留前端 — 這個 Unit 結束了,§10 收尾。

§10 · 收尾

這個 Unit 你帶走了什麼

資料庫不是讓 App「能存資料」,
是讓 App 從玩具 變成產品

Vibe coder 跟 AI 協作時的 7 個直覺:

  • · 講 spec 前能把資料放上 記憶體梯子 的某一階
  • · 聽到「丟資料庫」會浮現 四個契約(結構、查詢、並發、持久)
  • · 看到 AI 寫「read → modify → write」會 聞到 race
  • · 查詢慢的第一句是 「哪幾欄需要 index」
  • · AI 講「存起來了」會反問 「存哪一層?有副本嗎?」
  • · 給 AI 選型 prompt 時會先 對號入座到典型場景
  • · 規劃時會問 「半年後 10× 流量還跑得動嗎?」
📍 下一站 · Unit 1.2
兩大陣營對決:SQL vs NoSQL

知道資料庫的契約之後,下一步分得出兩個陣營的差別 — 關聯式怎麼想、文件式怎麼想,以及 ACID、JOIN、CAP 這些 CS 觀念。