結論先講

PostgreSQL 和 MySQL 各有主場。 PG 贏在 JSON 查詢(3.2 倍)、交易處理(天花板高 40%)、生態完整性(JSONB 讓你不用加 MongoDB)。MySQL 贏在大量寫入(2.5 倍)——如果你的場景是 80% 寫入,MySQL 真的比較快。大部分場景選 PG;寫入密集選 MySQL。

這一步怎麼來的:後端壓測發現 bcrypt 之外,DB 查詢是第二大效能影響因素。Go 的瓶頸被標記為「DB 查詢慢」,Django 的 pool=10 直接拖垮高 VU 表現。於是固定後端框架,只換 DB 來測。


為什麼測 DB 層

後端框架壓測發現 bcrypt 是共同瓶頸(第 6 篇)。但 bcrypt 之外,DB 查詢是第二大效能影響因素。Go 的瓶頸 被標記為「DB 查詢慢」,Django 的 pool=10 直接拖垮高 VU 表現。

這三篇 DB 測試把後端框架固定(Express-TS + Sequelize),只換 DB 變因,回答:PG vs MySQL 差多少?ORM 真的慢嗎?怎麼寫入最快?連線池開多大?


測試怎麼做的

跟後端框架壓測不同——DB 層的測試固定同一個後端,只換 DB:

項目設定
後端Express-TS(固定不變)
ORMSequelize(固定不變)
Docker4 CPU / 4 GB
DB Pool10
Cache關閉
比較對象PostgreSQL vs MySQL × 不同場景

這才是公平比較——改一個變因,其他全部不動。和 第 3 篇控制變因 講的原則一致。


7 項 DB 測試結果

1. ORM vs Raw SQL(讀寫 50:50)

方式PG RPSMySQL RPS
Sequelize ORM197183
Raw SQL215198

ORM 和手寫 SQL 的差距不到 10%。 很多人以為 ORM 很慢,實測差距沒有想像中大。ORM 的價值在開發速度和可維護性,這 10% 的效能損失完全可以接受。

但注意:這是「簡單 CRUD」的數字。複雜查詢(JOIN 3 張表 + subquery + GROUP BY)時,ORM 生成的 SQL 可能遠不如手寫 SQL 優化。建議:80% 用 ORM,20% 複雜查詢手寫 SQL。

2. JSON/JSONB 欄位查詢

DBJSON 查詢 RPS對比
PG JSONB6453.2 倍
MySQL JSON201基準

PG 的 JSONB 支援 GIN 索引,查詢 JSON 欄位可以走索引。MySQL 的 JSON 欄位查詢需要每次都 parse JSON——等於全表掃描。

這是 PG 最大的優勢。 如果你的應用需要存 JSON(用戶設定、產品規格、表單欄位),PG 一個資料庫就搞定,不用另外加 MongoDB。

3. 寫入密集場景(讀寫 20:80)

DBRPS
MySQL498
PG199

MySQL 在大量寫入時比 PG 快 2.5 倍

原因:PG 的 MVCC(Multi-Version Concurrency Control)在每次寫入時都會產生一個新版本的 row,舊版本需要 VACUUM 清理。大量寫入 = 大量垃圾版本 = VACUUM 壓力大。

MySQL 的 InnoDB 也用 MVCC,但它的 undo log 機制在高頻寫入時效率更好。

4. Bulk Insert 策略

方式RPS對比
逐筆 INSERT × 1008基準
ORM bulk8911 倍
Raw multi-value INSERT20826 倍

批次寫入比逐筆快 26 倍。 這個差距比「選哪個 ORM」或「選哪個 DB」的影響都大。

-- 逐筆:100 個 INSERT,100 個 roundtrip
INSERT INTO posts (title, body) VALUES ('A', '...');
INSERT INTO posts (title, body) VALUES ('B', '...');
-- ... 重複 100 次
 
-- 批次:1 個 INSERT,1 個 roundtrip
INSERT INTO posts (title, body) VALUES
  ('A', '...'),
  ('B', '...'),
  -- ... 100 筆
;

大部分 ORM 都支援 bulk insert(Sequelize 的 bulkCreate、TypeORM 的 insert().values([...])),但開發者常常忘記用。

5. Index 策略(100K rows)

Index 狀態讀取 RPS寫入 RPS
無 Index
正確 Index最佳平衡稍慢
過度 Index讀取不變明顯慢

過度 Index(每個欄位都建 index)會拖慢寫入——每次 INSERT/UPDATE 都要同時更新所有 index。

6. Transaction 鎖競爭(50 hot rows)

DBMax RPS備註
PG高 40%MVCC 讀不阻塞寫
MySQL基準InnoDB gap lock 較積極

PG 的 MVCC 讓讀取不會被寫入阻塞——讀舊版本就好。MySQL 的 InnoDB 在某些場景下會用 gap lock,讀寫互相阻塞。

7. MongoDB vs SQL

DBCRUD RPS對比
MongoDB1,6958.6 倍
PG ORM197基準

MongoDB 在純 CRUD(無 JOIN、無 Transaction)場景快 8.6 倍。但 MongoDB 4.0+ 的 multi-document transaction 效能不如 PG/MySQL,也不適合複雜的多表關聯查詢。


選 DB 的決策樹

你的場景是什麼?
├── 大部分是讀取 + 需要 JSON 查詢 → PostgreSQL
├── 大量寫入(日誌、IoT、事件紀錄) → MySQL
├── 純文件式存取、不需要 Transaction → MongoDB
├── 需要全文搜尋 → PostgreSQL + Elasticsearch
└── 不確定 → PostgreSQL(最通用)

和 Infra 層的連結

DB 選好了,接下來影響效能的是 怎麼連

  • 連線池大小: pool=5 vs pool=50 在高壓下差 70%(第 38 篇 會講)
  • Redis 快取: 加 Redis 做 cache-aside,讀取場景提升 6.5 倍
  • 讀寫分離: PG primary + replica,讀多場景有明顯效果

這些是 Infra 層 的主題。


下一篇

Bulk Insert 快 26 倍:DB 寫入的正確姿勢 — ORM vs Raw SQL 差 10%,但逐筆 vs 批次差 26 倍。Index 過多寫入變慢。Transaction 鎖怎麼避免。寫入優化的實戰指南。


本系列文章

完整 68 篇目錄見 系列首頁

← 上一篇:CSR vs SSR vs Islands:首屏速度的三種哲學 → 下一篇:Bulk Insert 快 26 倍:DB 寫入的正確姿勢