Postgres - 1
🐘 PostgreSQL 的誕生,是一場對「資料庫該長什麼樣子」的重新設計
PostgreSQL 的起點,來自 Stonebraker 團隊發現當時的關聯式資料庫很擅長存表格,卻很難處理更複雜的資料型態,因此乾脆重新設計一套更容易擴充的資料庫。
一段名字的演化史
整個歷史可以先用一條簡單的脈絡記下來,後面再展開每一段的背景。
Stonebraker 早期參與開發 Ingres,這是 1970 年代非常重要的關聯式資料庫研究專案,奠定了他日後對資料庫設計的基礎理解。
到了 1980 年代,Stonebraker 開始思考一個問題:如果資料庫除了 integer、string 這些基本型態,還希望支援更複雜的物件、規則甚至自訂型態,資料庫架構應該怎麼設計。於是 Berkeley 團隊啟動了新的 POSTGRES 專案。
後來 POSTGRES 加入 SQL 支援,逐漸演變成 Postgres95,最後在 1996 年正式改名為今天熟悉的 PostgreSQL。
名字怎麼來的:把 POST 加上 INGRES 就是 POSTGRES,可以直接理解成「Ingres 之後的下一個系統」,是一個延續前一代研究成果、再往前跨一步的命名方式。
Stonebraker 厲害的地方在於,他長期都在重新思考資料庫應該怎麼設計,而且很多研究最後真的變成業界使用的系統。他後來還參與了 Vertica、VoltDB 等資料庫相關專案,並在 2014 年獲得 ACM 圖靈獎。
資料庫應該可以被擴充
PostgreSQL 很重要的一個設計思想,就是資料庫不應該只能接受它原本規定好的資料型態,開發者應該可以自行擴充它。這個想法直接延續自當年 POSTGRES 專案的研究方向。
所以今天使用 PostgreSQL 時,可以看到很多很有特色的能力,例如自訂一個 ENUM 型態:
CREATE TYPE mood AS ENUM ( 'sad', 'ok', 'happy' );
甚至可以安裝 extension,讓 PostgreSQL 直接擁有原本不存在的能力:
CREATE EXTENSION postgis;
裝上 postgis 之後,PostgreSQL 就直接擁有了 GIS 地理資料處理能力。這種「資料庫本身可以被擴充」的味道,和 POSTGRES 當年的研究方向有很深的關係。
為什麼特別強調這五個字眼
PostgreSQL 的文件與生態圈裡,經常反覆出現這五個關鍵字,它們都指向同一件事,也就是讓資料庫可以被擴充。
Type:可以自訂資料型態,不侷限於內建的 integer、stringExtension:可以用套件形式擴充整套能力,例如postgis、pgvectorFunction:可以用多種語言撰寫自訂函式,塞進資料庫內部執行Operator:可以定義新的運算子,讓自訂型態也能參與比較與運算Index Method:可以擴充索引結構,讓新的資料型態也有對應的高效查詢方式
為什麼越來越多人選 PostgreSQL
PostgreSQL 越來越多人用,核心原因是它把免費、成熟、功能強、容易擴充同時做到了一個很高的水準,讓新專案在挑選資料庫時通常很難找到明顯的硬傷。
| 資料來源 | 年份 / 指標 | 數字 |
|---|---|---|
| Stack Overflow Developer Survey | 2018 | 約 33% 開發者使用 PostgreSQL |
| 2024 | 成長到約 49% | |
| 2025 | 「使用」與「想使用」兩項調查都排名最高 | |
| DB-Engines | 2026 年 8 月 | 所有資料庫中排名第 4,相較 2025 年同期分數增加 13.32;排名在前的是 Oracle、MySQL、SQL Server |
綜合這兩份數據比較準確的描述是:PostgreSQL 已經從開源資料庫的其中一個選擇,逐漸變成很多新系統預設會考慮的主力資料庫。
① 免費且能力完整
免費方案已足以支撐大量正式商業系統。
② Cloud 降低維運門檻
備份、升級、HA、監控多半交給雲端服務。
③ 擴充能力強
需求長大時可以先加能力,不急著換資料庫。
① 免費,而且能力已經非常完整
當免費方案已經能處理大量正式商業系統的需求,團隊自然很難說服自己一開始就支付昂貴的資料庫授權費。例如公司要做電商、CRM、ERP、SaaS、會員系統、訂單系統、金融 Backend,很多情況下 PostgreSQL 已經足夠應付。
因此新專案可能直接採用上面這條路徑,而不是先購買商業資料庫授權。
② Cloud 把維運門檻降低很多
以前選擇 PostgreSQL,還代表要懂不少 DBA 工作。現在雲端服務把備份、升級、HA、監控處理掉很多,選 PostgreSQL 的心理成本自然降低。
以前的做法
安裝 PostgreSQL,接著自行設定 replication、backup、failover、monitoring、upgrade,每一步都可能要親自處理。
現在的做法
各種 managed PostgreSQL 服務已經非常普遍,工程師的體驗逐漸簡化成建立 PostgreSQL、拿到 Connection String、開始寫程式。
這種維運門檻的下降,對 PostgreSQL 的普及非常重要。
③ 擴充能力非常強
PostgreSQL 很有競爭力的地方,是需求長大之後,常常可以先替 PostgreSQL 加能力,而不用立刻把資料搬去另一套資料庫。
- 需要 JSON 資料:加上
metadata JSONB欄位就能處理 - 需要地圖或 GIS:安裝
PostGISextension - 需要 Vector Search:安裝
pgvectorextension
DB-Engines 現在甚至直接把 PostgreSQL 標示成同時具備 relational、document、graph、spatial、vector 等多模型能力的資料庫。
④ AI 時代又給 PostgreSQL 一波機會
AI 應用需要 Vector Search,而 pgvector 讓很多已經使用 PostgreSQL 的團隊可以直接把向量放進原本的資料庫,少維護一套系統就是很大的誘惑。
原本做 RAG 這類應用時,架構可能需要考慮 PostgreSQL 加上一套獨立的 Vector Database。現在部分規模的系統可以先採用 PostgreSQL 加上 pgvector,讓架構少一個元件。
少一套獨立的 Vector Database,代表少一套權限管理、少一套 Backup 機制、少一套 Monitoring 設定、少一個可能掛掉的地方。這對小型與中型團隊尤其有吸引力。
Vector 是什麼
假設要用數字描述一杯飲料,可以自己規定三個維度:維度一是甜度,維度二是酸度,維度三是咖啡味,而且每個數值都介於 0 到 1 之間。
| 飲料 | 甜度 | 酸度 | 咖啡味 |
|---|---|---|---|
| 拿鐵 | 0.6 | 0.1 | 0.8 |
| 檸檬汁 | 0.3 | 0.9 | 0.0 |
| 美式咖啡 | 0.1 | 0.1 | 1.0 |
把每杯飲料都寫成 [甜度, 酸度, 咖啡味] 這樣的三個數字,就已經建立了一個非常簡單的三維 Vector 空間。
Embedding 是把內容轉成座標
Embedding 指的是把文字、圖片等內容轉換成一串 Vector 數字,讓電腦可以用數學方式比較它們的特徵與相似程度。Vector 和 Embedding 其實是上下游關係,原始資料先經過 Embedding,才變成 Vector。
人類看到「我要退款」和「我想把錢拿回來」,很自然會知道這兩句話語意接近,但跟「今天天氣很好」差很多。可是電腦如果只看文字表面,「我要退款」和「我想把錢拿回來」兩句話甚至沒有多少相同的字。Embedding 就是用來處理這個落差的。
假設有一個 Embedding Model,分別把三句話轉成 Vector:
flowchart TD
M["Embedding Model"] --> A["我要退款"]
M --> B["我想把錢拿回來"]
M --> C["今天天氣很好"]
A --> VA["Vector A [0.82, 0.21, -0.55, ...]"]
B --> VB["Vector B [0.79, 0.25, -0.51, ...]"]
C --> VC["Vector C [-0.32, 0.91, 0.17, ...]"]
VA -->|"距離很近"| VB
VC -.->|"距離很遠"| VA
轉成 Vector 之後,電腦就能實際計算它們之間的距離:Vector A 跟 Vector B 距離很近,Vector C 跟前兩者距離很遠,這正好對應到語意上「退款」跟「拿回錢」很接近,跟「天氣」無關。
Vector Database 到底解決什麼問題
Vector Database 真正有價值的地方,在於能快速找出距離最近的 Vector。單純把一串數字存進 VARCHAR,只完成了保存資料這件事,並沒有辦法回答距離相關的問題。
這就像把 GPS 座標 25.0330, 121.5654 存成 VARCHAR,當然可以存進去,但接下來如果被問到「找距離這個座標最近的 10 間店」,這串座標就只是一段文字。資料庫並不知道誰比較近、距離多少、要怎麼快速找出最近的 10 個,Vector 的處境也是一樣。
用 100 萬篇文章拆解這個需求
假設有 100 萬篇文章,每篇文章都有各自的 embedding。使用者搜尋「我買的東西可以退錢嗎」,Embedding Model 會把這句話轉成一個 Query Vector。
flowchart LR
Q["Query Vector [0.79, 0.14, -0.31]"] -->|"比較距離"| R1["Article 1 [0.81, 0.12, -0.33]"]
Q -->|"比較距離"| R2["Article 2 [-0.21, 0.92, 0.14]"]
Q -->|"比較距離"| R3["Article 3 [0.77, 0.15, -0.29]"]
Q -->|"比較距離"| R4["Article 1,000,000 [0.13, -0.54, 0.82]"]
R1 -->|"距離很近"| TOP["排序後取 Top 5"]
R3 -->|"距離很近"| TOP
R2 -.->|"距離很遠,排除"| TOP
R4 -.->|"距離很遠,排除"| TOP
核心需求變成:在 100 萬個 Vector 裡,快速找出跟目標 Vector 最接近的 Top 5。這才是 Vector Database 真正要解決的問題。
把 Vector 存成 VARCHAR 會卡在哪裡
假設真的把 Vector 存成 VARCHAR:
CREATE TABLE articles ( id BIGINT, content TEXT, embedding VARCHAR(10000) );
| id | content | embedding |
|---|---|---|
| 1 | 如何退款 | [0.81,0.12,-0.33] |
| 2 | 如何修改密碼 | [-0.21,0.92,0.14] |
| 3 | 商品退貨流程 | [0.77,0.15,-0.29] |
存進去完全沒問題,但如果要查詢距離最近的 5 筆:
SELECT * FROM articles ORDER BY ??? LIMIT 5;
ORDER BY 後面要接什麼,會發現需要先完成一連串手動加工才能做到:
- 把
VARCHAR解析成數字陣列 - 把每個維度拿出來
- 計算跟目標 Vector 的距離
- 跟大量資料逐筆比較
- 依距離排序
- 取出 Top 5
VARCHAR 本身沒有 Vector 的數學語意,資料庫不知道怎麼對一段純文字計算距離,所有加工都要應用程式自己處理。
PostgreSQL 加上 pgvector 差在哪裡
裝了 pgvector 之後,可以直接宣告一個真正的 Vector 型態欄位:
CREATE TABLE articles ( id BIGSERIAL PRIMARY KEY, content TEXT, embedding vector(1536) );
資料庫現在真正知道 embedding 是一個 1536 維的 Vector,所以可以直接進行 Vector Distance Search:
SELECT * FROM articles ORDER BY embedding <-> '[0.79, 0.14, ...]' LIMIT 5;
這一段 ORDER BY embedding <-> '...' 已經跟 VARCHAR 存法有本質上的差異,資料庫自己知道怎麼計算距離,不需要應用程式手動解析。
Vector Index 為什麼重要
當 Vector 數量很大時,真正讓搜尋實用的能力之一,是透過專門的 Vector Index,避免每次查詢都要完整掃描所有 Vector。pgvector 支援例如 HNSW、IVFFlat 這類索引結構,不需要先研究背後演算法,只需要知道它們的目的是縮小搜尋範圍。
沒有適合的 Index
100 萬個 Vector 全部逐一比較,才能找出 Top 10。
有 Vector Index
先利用索引縮小搜尋範圍,再找出 Top 10。
這有點類似以前熟悉的 SQL Index,例如查詢 WHERE user_id = 9527 時,不會希望資料庫在 1000 萬筆使用者裡逐筆比對,才終於找到 9527,所以會建立 B-tree index。Vector Search 也有類似的需求,只是「找最相似資料」跟「等值查詢 user_id」是不同性質的問題,因此使用的索引結構也不一樣。
flowchart TD
PG["PostgreSQL"] -->|"傳統條件查詢"| SQL["SQL 世界:price < 3000、stock > 0"]
PG -->|"語意相似度查詢"| VEC["Vector 世界:語意是否相似、日系 / 夏天 / 簡約"]
SQL --> RESULT["搜尋結果"]
VEC --> RESULT
同一個 PostgreSQL,一邊處理傳統的條件式 SQL 查詢,一邊處理語意層面的 Vector 相似度查詢,最後匯回同一份搜尋結果,這正是 PostgreSQL 擴充能力在 AI 時代最直接的體現。


