跳轉到

1969 - Bachman 網路模型(集合關係與導航式資料庫)#

案件摘要#

1969 年,Charles W. Bachman(1924–2017)——在 GE 開發過 IDS (Integrated Data Store,1963 上線,第一個網路資料庫)的老偵探—— 把他的辦案手法整理成一套網路資料模型, 並由 CODASYL(COBOL 的標準委員會)成立 DBTG (Data Base Task Group)著手標準化(1971 年報告定案)。 他的破案關鍵只有一個,卻直搗層次模型的死穴:

\[ \boxed{\text{一筆記錄可以有多個「父親」——樹升級成圖(網路)}} \]

用「集合(set)」表示一對多的連結,用「導航(navigational)」 沿指標走訪資料——程式設計師親自當領航員。 1973 年,Bachman 獲圖靈獎——首位資料庫得主, 演說題目一針見血:《The Programmer as Navigator》(程式設計師即領航員)。

\[ \text{層次(1961)} \xrightarrow{\text{Bachman(1969/1971)}} \text{網路(圖)}. \]

前因 -- 為什麼會有這個案子#

  • 計算的理論基礎(1936): 資料庫是圖靈機思想(程式 = 資料)的工程實現 (見 ../資訊科學/1936-圖靈機.md)——
\[ \text{通用圖靈機(1936)} \xrightarrow{} \text{資料可以被結構化與查詢}. \]
  • 層次模型的死穴(1961): IMS 證明了「一份資料、多個程式共用」可行(見 1961-IBM層次資料庫.md), 但留下了兩條懸案:
\[ \boxed{\text{子記錄只能有一個父親;多對多資料無法表示}} \]

例如:同一個「軸承」由兩家供應商供貨——樹只能複製兩份, 資料重複、更新異常。

\[ \text{多對多需求} \xrightarrow{\text{樹的死穴}} \text{複製資料(不是解決問題)}. \]
  • GE 的 IDS(1963): Bachman 在奇異公司(General Electric)為製造業開發 IDS—— 第一個用「指標鏈結」組織資料的系統,先於標準問世。
\[ \text{IDS(1963)} \xrightarrow{\text{Bachman 的實戰經驗}} \text{網路模型(1969)}. \]
  • 演算法的時代精神(1968): Knuth 的《The Art of Computer Programming》第一卷 (見 ../資訊科學/1969-克努特演算法藝術.md)把指標、鏈結串列、樹 的操作整理成嚴謹的數學——
\[ \text{指標與鏈結(Knuth)} \xrightarrow{\text{Bachman}} \text{資料庫的指標鏈結理論}. \]

同時 CODASYL 正在標準化 COBOL,商業資料處理需要一個標準的資料庫介面。

線索與推理 -- 數學式、程式、理論#

第一條線索:網路(圖)vs 樹#

網路模型 = 一個有向圖 \(G = (V, E)\) : - \(V\) :記錄(record)的集合; - \(E \subseteq V \times V\) :連結(link)——一筆記錄可以有多個父親。

\[ \text{層次模型} = \text{樹} \subset \text{圖} = \text{網路模型}. \]
\[ \boxed{\text{樹是圖的特例:網路模型嚴格涵蓋層次模型}} \]

第二條線索:集合(set)型記錄關係#

Bachman 的核心發明——set(集合): - 一個 set = 一個首記錄(owner) + 若干成員記錄(member); - 成員之間用指標鏈串起來(循環鏈結串列)。

\[ \text{set } S = \big(\text{owner}(S),\ \text{members}(S)\big), \quad \text{members}(S) \subseteq V. \]

多對多 = 同一筆記錄參與多個 set:

\[ \exists\, r \in V:\ r \in \text{members}(S_1) \wedge r \in \text{members}(S_2). \]

例如「軸承 \(P_2\) 」同時是 \(S_1\) (供應商一供貨)與 \(S_2\) (供應商二供貨)的成員—— 不用複製資料!

CODASYL 的基本操作(DBTG 報告,1971 定案): - FIND:依鍵值或位置定位一筆記錄(游標停在這裡); - GET NEXT:沿 set 指標走到下一個成員; - GET OWNER:沿指標反向找到首記錄; - INSERT / REMOVE:把成員加入或移出 set。

導航式查詢 = 一連串的 FIND → GET NEXT 指令:

\[ \text{query} = \text{FIND}(S_1) \to \text{GET NEXT} \to \cdots \to \text{GET OWNER}. \]

代價:

\[ \boxed{\text{程式必須知道資料的每一條路徑——路徑改一步,程式崩潰}} \]

這是「邏輯資料相依」的殘留——層次模型的病沒有根治,只是緩解。

Python:小型網路資料庫與導航式查詢#

# Bachman 網路資料庫:記錄(record)+ 集合(set)連結 + 導航式查詢

class Record:
    """一筆網路資料庫記錄:資料欄位 + 它參與的所有集合連結"""
    def __init__(self, key, **fields):
        self.key = key
        self.fields = fields
        self.members = []           # 我當「首記錄」,指向我的成員(set 的一對多)

    def connect(self, *records):
        for r in records:
            self.members.append(r)  # 建 set:self 為 owner,r 為 member
        return self

class NetworkDB:
    """網路資料庫:所有記錄 + FIND / GET NEXT 的導航式操作"""
    def __init__(self):
        self.records = {}

    def add(self, rec):
        self.records[rec.key] = rec
        return rec

    def find(self, key):
        """FIND:依鍵值定位記錄(導航的起點)"""
        return self.records[key]

    def get_next(self, owner, i):
        """GET NEXT:沿 set 指標走到下一個成員"""
        if i < len(owner.members):
            return owner.members[i]
        return None

# ---- 建立資料庫:供應商—零件(多對多網路,不是樹!)----
db = NetworkDB()
s1 = db.add(Record("S1", city="台北"))
s2 = db.add(Record("S2", city="高雄"))
s3 = db.add(Record("S3", city="台中"))
p1 = db.add(Record("P1", name="螺絲"))
p2 = db.add(Record("P2", name="軸承"))
p3 = db.add(Record("P3", name="齒輪"))

# 同一筆記錄可以出現在多個 set 中 → 網路(圖),不是樹
s1.connect(p1, p2)
s2.connect(p2, p3)
s3.connect(p1, p3)

# ---- 查詢 1:FIND + GET NEXT 導航式遍歷 ----
print("查詢 1:導航式遍歷(FIND + GET NEXT)")
for skey in ["S1", "S2", "S3"]:
    s = db.find(skey)
    parts = []
    i, m = 0, db.get_next(s, 0)
    while m is not None:                     # 沿指標導航
        parts.append(m.key)
        i += 1
        m = db.get_next(s, i)
    print(f"  FIND {skey}({s.fields['city']})→ GET NEXT → {parts}")

# ---- 查詢 2:反向導航(零件 → 供應商)----
print("\n查詢 2:反向導航需要另一組指標(多對多的代價)")
print("  P2 的供應商:S1(台北)、S2(高雄)  ← 需維護反向集合指標")

# ---- 查詢 3:驗證這是「圖」不是「樹」----
print("\n查詢 3:結構驗證——同一記錄有多個父親(網路 vs 樹)")
parent_count = {k: 0 for k in db.records}
for rec in db.records.values():
    for m in rec.members:
        parent_count[m.key] += 1
for k, n in parent_count.items():
    kind = "樹(一個父親)" if n <= 1 else "網路(多個首記錄)"
    print(f"  記錄 {k}:被 {n} 條 set 指到 → {kind}")

# ---- 結案的伏筆 ----
print("\n伏筆:導航式查詢的代價")
print("  程式設計師必須親自寫出 FIND → GET NEXT 的每一步路徑,")
print("  資料路徑改一個位元,程式就全面崩潰。")
print("  → 「能否用數學取代導航?」——這是 Codd(1970)要偵辦的下一案。")
輸出:
查詢 1:導航式遍歷(FIND + GET NEXT)
  FIND S1(台北)→ GET NEXT → ['P1', 'P2']
  FIND S2(高雄)→ GET NEXT → ['P2', 'P3']
  FIND S3(台中)→ GET NEXT → ['P1', 'P3']

查詢 2:反向導航需要另一組指標(多對多的代價)
  P2 的供應商:S1(台北)、S2(高雄)  ← 需維護反向集合指標

查詢 3:結構驗證——同一記錄有多個父親(網路 vs 樹)
  記錄 S1:被 0 條 set 指到 → 樹(一個父親)
  記錄 S2:被 0 條 set 指到 → 樹(一個父親)
  記錄 S3:被 0 條 set 指到 → 樹(一個父親)
  記錄 P1:被 2 條 set 指到 → 網路(多個首記錄)
  記錄 P2:被 2 條 set 指到 → 網路(多個首記錄)
  記錄 P3:被 2 條 set 指到 → 網路(多個首記錄)

伏筆:導航式查詢的代價
  程式設計師必須親自寫出 FIND → GET NEXT 的每一步路徑,
  資料路徑改一個位元,程式就全面崩潰。
  → 「能否用數學取代導航?」——這是 Codd(1970)要偵辦的下一案。

結案 -- 後果與影響#

  • 標準的誕生(1971):
\[ \boxed{\text{CODASYL/DBTG 報告:網路模型成為商業標準}} \]

1970 年代,幾乎所有大廠(IBM 之外的 Honeywell、Univac、CINCOM 等) 都推出 CODASYL 系統——網路模型統治了 1970 年代的資料庫市場。 - 首位資料庫圖靈獎得主(1973):

\[ \text{Bachman} \xrightarrow{1973 \text{ 圖靈獎}} \text{資料庫成為一門顯學} \]

演說《The Programmer as Navigator》宣告: 程式設計師的新身分是資料世界的領航員—— 這既是網路模型的宣言,也精準暴露了它的問題。 - 路線之爭:Bachman vs Codd:

\[ \text{Bachman:導航(工程直覺)} \quad\text{vs}\quad \text{Codd:關聯代數(數學)} \]
  • Bachman:資料有結構,程式沿結構走——效率與實務;
  • Codd:程式只說「要什麼」,不說「怎麼走」——獨立與簡單 (見 1970-科德關聯式模型.md)。 這場論戰以 Codd 的勝利告終,但導航式思維從未消失—— 它轉世為物件導向資料庫、圖資料庫(Neo4j)、NoSQL。
  • 複雜性為關聯式革命鋪路:
\[ \text{程式需知道資料路徑} \xrightarrow{\text{革命伏筆}} \text{Codd 的資料獨立性(1970)} \]

CODASYL 系統的查詢程式碼冗長且易碎—— 正是這種複雜性,讓 Codd 的「用數學取代導航」一擊中的。 - 歷史定位:Bachman 是資料庫史的第二章—— 他把樹升級成圖、把資料連結標準化, 也用一場圖靈獎演說,親手寫下了自己時代的第一份「辯護狀」與「起訴書」。

\[ \text{樹(1966)} \xrightarrow{\text{Bachman(1969)}} \text{圖(1971)} \xrightarrow{\text{Codd(1970)}} \text{表(關聯)}. \]

關鍵人物與文獻#

  • Charles W. Bachman(1924–2017):IDS(1963);CODASYL/DBTG 報告(1971); 《The Programmer as Navigator》(1973 圖靈獎演說)。
  • CODASYL / DBTG:網路資料模型的標準化組織(1971 定案)。
  • General Electric / Honeywell:IDS 的開發與後續商品化。
  • E. F. Codd:關聯式模型(1970)——路線之爭的對手(見 1970-科德關聯式模型.md)。
  • 相關案件:../資訊科學/1936-圖靈機.md、1961-IBM層次資料庫.md、../資訊科學/1969-克努特演算法藝術.md。