1986 - 波斯特 Postgres(物件關聯式資料庫)#
案件摘要#
1986 年,Michael Stonebraker(1943–) 在 Berkeley 啟動 Postgres(Post-Ingres)——Ingres 之後的第二戰場:
Stonebraker 的問題:關聯式模型的表格太「平」—— 真實世界的資料是複雜物件(地圖、CAD 圖形、文件、影像):
他的解法:擴充關聯式模型,而非推翻它—— - 自訂型別(ADT):使用者自己定義資料型別與函式; - 繼承(inheritance):表可以繼承表(物件導向的思想進了資料庫); - 規則系統與觸發器:資料庫主動反應(rules、triggers)。
1995 年,Berkeley 把 Postgres 交棒給兩名學生—— 他們加上 SQL 直譯器,改名 PostgreSQL,開源釋出—— 至今最強的開源資料庫之一。 2014 年,Stonebraker 獲圖靈獎——表彰他對資料庫 「概念與原型」的兩度革命(Ingres 與 Postgres)。
前因 -- 為什麼會有這個案子#
- Ingres 的成功與極限(1974–1985): 見
1974-斯東布雷克Ingres.md(稍後建立)—— Stonebraker 在 Berkeley 用 Ingres 證明了關聯式資料庫的工程可行性 (QUEL 語言、關係代數的實現)。 但 Ingres 之後,Stonebraker 問:下一個問題是什麼?
1985 年,他把 Ingres 商業化交棒(Ingres Corporation), 回到 Berkeley 啟動 Postgres。 - 新應用的複雜資料(1980s): 1980 年代的新應用——地理資訊系統(GIS)、CAD/CAM、影像文件—— 資料不是「員工姓名、薪水」的平坦表格:
用關聯式表格存多邊形?要拆成十幾個數字欄位——查詢時再組合——
- Simula 的物件導向思想(1967): 見
../資訊科學/1967-達爾尼加德Simula.md—— Dahl 與 Nygaard 的 Simula 67 引入類別、繼承、物件:
物件 = 資料 + 方法——這個思想從程式語言移植到資料庫: 表格若能「知道自己的型別與操作」,就能存複雜物件。 - Chen 的實體關係模型(1976): 見 1976-陳氏實體關係模型.md(稍後建立)—— Peter Chen 的 E-R 模型把「實體、屬性、關係」變成設計語言——
Chen 的「實體」與 Stonebraker 的「物件」是同源的概念。 - 物件導向資料庫的競爭(1980s): OODBMS 陣營(GemStone、ObjectStore)主張推翻關聯式、全面物件化—— Stonebraker 反對:SQL 與關聯式的 20 年投資不能丟——
歷史站在 Stonebraker 這邊。
線索與推理 -- 數學式、程式、理論#
第一條線索:型別系統的擴充(自訂型別 ADT)#
關聯式模型的型別(內建、固定):整數、字串、日期——
Postgres 的擴充:使用者自訂抽象資料型別(ADT)—— 型別 = 內部表示 + 操作函式:
例如自訂「圓」型別:
- 內部表示:圓心與半徑;
- 操作:面積、包含、相交——使用者用 C 語言寫、動態載入。
查詢語言 POSTQUEL 直接呼叫:
retrieve (s.name) where area(s.shape) > 50
第二條線索:複雜物件查詢與繼承#
繼承(inheritance):表可以有「父表」:
CREATE TABLE shapes (name text);
CREATE TABLE circles (r real) INHERITS (shapes);
shapes 自動包含子表 circles 的所有列: 這是 Simula 的類別階層直接搬到資料表——
複雜物件的查詢:物件欄位可以巢狀(Postgres 早期版本支援 路徑表示式):
規則系統(rules):資料主動反應——
這是觸發器(trigger)的前身——資料庫從「被動的倉庫」 變成「主動的代理人」。
第三條線索:貝葉斯式的取捨——擴充而非推翻#
Stonebraker 的論證(1986):
取捨: - 保留:關係代數、SQL(後來)、事務、優化器—— 20 年的理論與工程不能丟; - 新增:自訂型別、繼承、規則—— 表達複雜世界。
工程代價:Postgres 的規則系統太慢(早期版本),繼承讓 優化器頭痛——理想的擴充被現實折衷(1995 交棒時大幅精簡)。
Python:用 sqlite3 自訂函式/JSON 模擬物件關聯式查詢#
# 1) 自訂型別 + 複雜物件:用 JSON 模擬 Postgres 的物件欄位
import sqlite3, json
conn = sqlite3.connect(":memory:")
cur = conn.cursor()
cur.execute("CREATE TABLE shapes (name TEXT, data TEXT)") # data = 物件(自訂型別)
# data 欄位存「自訂型別」:circle / rect 物件(Postgres 允許這種複合型別)
objs = [
("紅圓", json.dumps({"type": "circle", "cx": 0, "cy": 0, "r": 5})),
("藍矩形", json.dumps({"type": "rect", "x": 1, "y": 2, "w": 4, "h": 3})),
("綠圓", json.dumps({"type": "circle", "cx": 10, "cy": 10, "r": 1})),
]
cur.executemany("INSERT INTO shapes VALUES (?,?)", objs)
conn.commit()
def area(data): # 相當於 Postgres 的自訂函式(C 語言擴充 → 這裡用 Python)
o = json.loads(data)
if o["type"] == "circle":
return 3.14159 * o["r"] ** 2
return o["w"] * o["h"]
conn.create_function("area", 1, area) # 註冊自訂函式 → SQL 可直接呼叫!
print("物件關聯式查詢:自訂函式 area() 算複雜物件面積")
cur.execute("SELECT name, data, area(data) FROM shapes ORDER BY area(data) DESC")
for name, data, a in cur.fetchall():
o = json.loads(data)
desc = f"半徑 {o['r']} 的圓" if o["type"] == "circle" else f"{o['w']}×{o['h']} 矩形"
print(f" {name}({desc}):面積 {a:.2f}")
# 2) 依「物件內部欄位」查詢:JSON 提取(模擬 Postgres 的路徑表示式 data->'type')
print("\n查詢物件內部欄位(data->'type' = 'circle')")
cur.execute("SELECT name FROM shapes WHERE json_extract(data, '$.type') = 'circle'")
print(" 圓形物件:", [r[0] for r in cur.fetchall()])
# 3) 繼承(inheritance):circles 表「繼承」shapes 表
print("\n繼承測試(Postgres:CREATE TABLE circles () INHERITS (shapes))")
cur.execute("""CREATE TABLE circles (
data TEXT CHECK(json_extract(data, '$.type') = 'circle')
)""")
cur.execute("INSERT INTO shapes VALUES ('紫圓', ?)",
(json.dumps({"type": "circle", "cx": 3, "cy": 3, "r": 2}),))
cur.execute("SELECT name FROM shapes WHERE json_extract(data, '$.type') = 'circle'")
print(" shapes + 子類別的圓:", [r[0] for r in cur.fetchall()])
conn.close()
物件關聯式查詢:自訂函式 area() 算複雜物件面積
紅圓(半徑 5 的圓):面積 78.54
藍矩形(4×3 矩形):面積 12.00
綠圓(半徑 1 的圓):面積 3.14
查詢物件內部欄位(data->'type' = 'circle')
圓形物件: ['紅圓', '綠圓']
繼承測試(Postgres:CREATE TABLE circles () INHERITS (shapes))
shapes + 子類別的圓: ['紅圓', '綠圓', '紫圓']
結案 -- 後果與影響#
- PostgreSQL 的誕生(1995):
兩名學生:Andrew Yu 與 Jolly Chen 把 POSTQUEL 換成 SQL 直譯器, 改名 Postgres95 → PostgreSQL——開源釋出(BSD 授權)。
- 至今最強開源資料庫之一(1995 → 2026): PostgreSQL 30 年由全球社群接力維護:
- JSON 支援(2012):物件關聯式的理想在 30 年後以 JSON 落地——
- GIS 的 PostGIS:全球地理資訊系統的事實標準—— Postgres 原始目標(複雜資料)的勝利;
- 雲端時代的寵兒:AWS Aurora、Google AlloyDB、Supabase—— 都選 PostgreSQL 為基底。
- OODBMS 陣營的消亡:
Stonebraker 的「擴充而非推翻」贏了—— 物件的思想(自訂型別、JSON、複合型別)被吸進關聯式, 而非取代它。 - Stonebraker 的圖靈獎(2014):
表彰:對資料庫系統「概念與原型」的奠基貢獻—— 兩度革命、兩度交棒(Ingres 公司、PostgreSQL 社群)。 他也是 CQS 的反例演說家:晚年推動 NewSQL 與 「one size does not fit all」——見 2012-谷歌Spanner全球資料庫.md (稍後建立)的時代背景。 - 規則系統的遺產: Postgres 的規則系統演變成觸發器(triggers)與 具體化視圖(materialized views)——
- 開源的伏筆:
同年開源的 MySQL(見 1995-MySQL開源資料庫.md,稍後建立) 與 PostgreSQL 展開 30 年的雙雄競爭—— 開源資料庫時代的兩位主角就此登場。 - 理論的迴響:
Ingres 證明了關聯式可行,Postgres 證明了關聯式可以進化。
關鍵人物與文獻#
- M. Stonebraker:The Design of POSTGRES(1986);Ingres(1974); Postgres(1986);2014 圖靈獎;「one size does not fit all」。
- O. Dahl & K. Nygaard:Simula 67(1967)——物件導向思想(繼承的來源)。
- P. Chen:實體關係模型(1976)——實體概念的先驅。
- A. Yu & J. Chen:Postgres95(1995)——SQL 直譯器與開源釋出。
- Lawrence Rowe:Postgres 的共同研究者(Berkeley)。
- 相關案件:
1974-斯東布雷克Ingres.md(稍後建立)、../資訊科學/1967-達爾尼加德Simula.md、1976-陳氏實體關係模型.md(稍後建立)、1979-甲骨文ORACLE.md、1981-葛雷交易ACID.md、1995-MySQL開源資料庫.md(稍後建立)、../資訊科學/1936-圖靈機.md。