SQL vs NoSQL:你的 App 應該使用哪種資料庫?
SQL 資料庫(也稱為關聯式資料庫)將資料存放在具有固定結構的資料表中,也就是列與欄,並把相關的資料表連結在一起。你使用 SQL 語言來查詢。Postgres、MySQL 與 SQLite 都是例子。NoSQL 資料庫則使用其他方式儲存資料,例如文件、鍵值配對、寬欄位或圖形,通常允許較有彈性的結構。MongoDB、Redis、DynamoDB 與 Firestore 都是例子。對大多數商業 App 而言,SQL 資料庫是合理的預設選擇;NoSQL 則在特定工作上表現出色。
使用 AI 製作時,為什麼這個選擇很重要
資料庫是 App 中日後最難更動的部分之一。畫面可以在一個下午重新設計,但要把多年的客戶資料搬到另一種資料庫,就是一個專案。
當 AI App 製作工具替你加入資料儲存功能時,它其實是在為你選擇其中一種。了解兩者的差異,能幫助你:
- 理解你的資料長什麼樣子,以及它能否回答你之後會問的問題(「每個月各產品的營收」)。
- 評估平台的選擇。 有些平台建立在文件資料庫上,有些則建立在關聯式資料庫上。常見的例子請參閱 Supabase vs Firebase。
- 避免被特定廠商綁定。 SQL 是共通的標準,因此關聯式資料通常比較容易在不同服務商之間遷移。
日常生活中的比喻
SQL 資料庫就像一組設計精良、欄位嚴格的試算表:一張表放客戶,一張表放訂單,每一筆訂單列都透過 ID 指向對應的客戶列。每張表中的每一列都有相同的欄位。它需要一些規劃,但跨表提問很容易,資料也能保持整齊。
NoSQL 文件資料庫則像一個裝滿資料夾的檔案櫃。每位客戶的資料夾可以把他的資訊和訂單放在一起,而且某個資料夾可以放其他資料夾沒有的額外文件。要快速取得單一客戶的完整紀錄很方便。但若要回答「上個月每個人買了什麼?」,就得打開很多資料夾。
真正的差異
| SQL(關聯式) | NoSQL | |
|---|---|---|
| 資料形態 | 具有固定欄位的資料表 | 文件、鍵值、寬欄位或圖形 |
| 結構 | 事先定義結構,透過遷移(migration)調整 | 通常較有彈性;結構由應用程式碼決定,甚至可能不強制 |
| 關係 | 內建:外部鍵與串聯(join) | 通常靠巢狀資料或應用程式碼處理 |
| 查詢語言 | SQL,為共通標準 | 每個產品各不相同 |
| 一致性 | 強交易是標準配備 | 依產品與設定而定;現在許多產品也提供交易功能 |
| 擴展 | 傳統上是垂直擴展(換更大的伺服器);水平擴展可行但較困難 | 許多產品設計為可分散到多台伺服器 |
| 擅長 | 商業資料、報表、關係很多的任何資料 | 大量的簡單紀錄、快取、彈性內容 |
| 例子 | Postgres、MySQL、SQLite、SQL Server | MongoDB、Redis、DynamoDB、Firestore、Cassandra、Neo4j |
「NoSQL」並不是單一種東西。主要類型如下:
| 類型 | 儲存方式 | 典型用途 |
|---|---|---|
| 文件(MongoDB、Firestore) | 類 JSON 的文件 | 內容、商品目錄、紀錄格式多變的 App |
| 鍵值(Redis、DynamoDB) | 透過鍵查找對應的值 | 快取、工作階段、計數器 |
| 寬欄位(Cassandra) | 欄位集合有彈性的列 | 寫入量龐大的資料集 |
| 圖形(Neo4j) | 節點與連線 | 社群網路、推薦系統 |
實際範例:同一份商店資料,兩種存法
以一間小型網路商店為例,其中有一位客戶和她的訂單。
SQL(關聯式): 資料被拆分到多張資料表,並透過 ID 相互連結。
-- customers: id=1, name='Lena Ortiz'
-- orders: id=101, customer_id=1, total=42.00
-- id=103, customer_id=1, total=25.00
SELECT c.name, SUM(o.total)
FROM customers c JOIN orders o ON o.customer_id = c.id
GROUP BY c.name;
如果 Lena 更改了電子郵件,只需要在一個地方更新。要查詢「本月每位客戶的總銷售額」,只需要一條查詢。
NoSQL(文件): 她的訂單可以直接放在她的文件內。
{
"_id": "cust_1",
"name": "Lena Ortiz",
"email": "lena@example.com",
"orders": [
{ "id": 101, "total": 42.00, "items": ["Green tea"] },
{ "id": 103, "total": 25.00, "items": ["Teapot"] }
]
}
載入 Lena 的個人頁面(包含她所有訂單)只需要一次讀取。但跨所有客戶的問題,例如本月最暢銷的商品,就需要更多工作;而且如果同一個商品的資訊被複製到許多訂單中,要保持同步就成了 App 的責任。
兩者都沒有錯。關鍵在於你的 App 最常用的是哪一種模式。
如何選擇
如果符合以下情況,關聯式 SQL 資料庫通常是合適的預設選擇:
- 你的資料有很多關係,例如使用者、團隊、預約、發票、商品。
- 你需要跨紀錄的報表、篩選與總計。
- 正確性很重要,例如金錢、庫存數量、權限。
如果符合以下情況,就值得考慮 NoSQL 資料庫:
- 你需要快速的快取或工作階段儲存空間。Redis 在這方面很常見,而且通常是搭配 SQL 資料庫一起使用。
- 你的紀錄數量非常龐大,而且簡單、彼此獨立,例如事件紀錄或感測器讀數。
- 你使用的平台是以某種 NoSQL 為核心,例如 Firebase 的 Firestore,而且它的即時功能是你的主要考量。
許多 App 會同時使用兩者:以 SQL 作為主要的資料來源,並以 NoSQL 儲存來做快取或支援特定功能。
常見術語
| 術語 | 意思 |
|---|---|
| 關聯式資料庫 | 由相互連結的資料表組成的 SQL 資料庫。 |
| 結構(Schema) | 資料的固定格式定義。 |
| 串聯(Join) | 在一次查詢中合併兩張資料表中相關的列。 |
| 文件 | 文件資料庫中自成一體、類 JSON 的紀錄。 |
| 反正規化(Denormalisation) | 為了讓讀取更快,將資料複製到多個位置。 |
| ACID | 保證交易可靠的特性:全部成功或全部失敗、一致、隔離且持久。 |
| 水平擴展(Horizontal scaling) | 將資料分散到多台伺服器,而不是只使用一台更大的伺服器。 |
常見的誤解
- 「NoSQL 就是沒有結構」。 你的資料一定有某種形態。使用 NoSQL 時,資料庫可能不會強制執行這個形態,因此必須由你的程式碼來確保。
- 「SQL 無法擴展」。 關聯式資料庫能支撐非常大型的服務。大多數 App 根本不會接近它們的上限。
- 「NoSQL 永遠比較快」。 只有在它所設計的模式下才是如此。跨多種資料的報表可能反而比較慢。
- 「一旦選定就必須永遠使用」。 許多 App 會同時結合兩者。而且像 Postgres 這樣的 SQL 資料庫也能儲存 JSON,因此少數彈性欄位不必動用 NoSQL。
- 「NoSQL 就代表不能使用 SQL」。 這個名稱通常被理解為「不只是 SQL」,而且有些 NoSQL 產品也提供類似 SQL 的查詢語言。
可以問 AI 製作工具的問題
- 「這個 App 使用哪一種資料庫?為什麼它適合我的資料?」
- 「請畫出資料表或集合,以及它們之間的關係。」
- 「六個月後我會想要哪些報表?這個資料庫能輕鬆回答嗎?」
- 「如果有幾個欄位確實需要彈性,請把它們以 JSON 的形式存在 Postgres 中,而不是另外新增第二個資料庫。」
- 「只有在實際測量到速度問題時,才加入快取。」
Mythex 中的資料庫
Mythex 會為需要資料庫的每個專案提供一個專用的 Postgres 資料庫,也就是關聯式 SQL 資料庫。你可以在聊天中要求,或使用 /database 指令新增,並在需要時加入(Database)。這適合大多數商業 App,例如使用者、預約、訂單與報表。如果你需要連接特定的外部服務,例如託管的文件資料庫,代理可以撰寫程式碼,並使用你儲存為專案機密的金鑰來連接。若要進一步了解 SQL 這個語言本身,請閱讀 什麼是 SQL。
常見問題
SQL 和 NoSQL 的主要差異是什麼?
SQL 資料庫將資料存放在具有固定結構的資料表中,並把相關的資料表連結在一起,你使用 SQL 語言來查詢。NoSQL 資料庫則使用其他模型,例如文件、鍵值配對、寬欄位或圖形,通常允許較有彈性的結構,而且每個產品都有自己的查詢方式。
NoSQL 比 SQL 快嗎?
一般而言並非如此。兩者在各自設計的存取模式下都很快。鍵值儲存非常擅長依照鍵值取出單一項目;關聯式資料庫則擅長篩選、串聯與彙總相關資料。設計與索引的重要性,遠高於資料庫屬於哪一類。
新創公司或小型 App 哪種比較好?
對大多數商業 App 而言,例如客戶、訂單、預約、使用者與權限,Postgres 等關聯式 SQL 資料庫是可靠的預設選擇。NoSQL 則適合特定需求,例如快取、部分平台上的即時同步,或是大量簡單且彼此獨立的紀錄。
MongoDB 是 SQL 還是 NoSQL?
MongoDB 是 NoSQL 文件資料庫。它將紀錄儲存為彈性的類 JSON 文件,而不是資料表中的列。
SQL 資料庫可以儲存 JSON 嗎?
可以。Postgres 提供 jsonb 類型,用於儲存與查詢 JSON,MySQL 與 SQLite 也支援 JSON。這讓許多 App 能以關聯式的核心資料為主,再搭配幾個彈性欄位,不必另外使用 NoSQL 資料庫。