跳轉到

1961 - IBM 層次資料庫(IMS:為登月計畫而生的樹狀資料庫)#

案件摘要#

1961 年,IBM 的工程師團隊(Vernon Watts、Oscar Gilbert 等人, 與 North American Aviation 的 Rockwell 合作)接下一樁「不能失敗」的案子: 阿波羅登月計畫的物料清單(BOM)管理系統。 一支太空船有數百萬個零件,每個零件又由子零件組成—— 樹狀結構應聲而出:

\[ \boxed{\text{資料 = 樹:每筆記錄有一個父親,可以有多個兒子}} \]

這就是 IMS(Information Management System)—— 第一個大規模商用的層次資料庫(1966 年隨阿波羅計畫上線,1968 年正式發售)。 資料獨立的萌芽也在此埋下:程式透過「層次路徑」取資料, 而不再直接讀寫磁帶上的原始位元組。

\[ \text{磁帶檔案處理} \xrightarrow{\text{IMS(1961/1966)}} \text{樹狀資料模型}. \]

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

  • 計算的理論基礎(1936): 一切要從 圖靈機 說起(見 ../資訊科學/1936-圖靈機.md)——
\[ \boxed{\text{程式 = 資料(通用圖靈機的革命性思想)}} \]

資料庫正是這個思想的大型工程實現:資料可以被結構化地儲存與查詢。 - 1960 年代磁帶與檔案處理的混亂: 當時的「資料管理」是這樣辦案的: - 資料存在磁帶上(順序存取,找一筆記錄要從頭倒帶); - 每個程式自帶檔案格式——同一份物料資料,會計程式與工程程式 各自維護一份副本; - 資料重複、更新不同步:改了一處忘了另一處,數字對不上。

\[ \text{一筆資料 } N \text{ 個副本} \xrightarrow{\text{更新異常}} \text{數字對不上}. \]
  • 阿波羅計畫的物料危機(1961): North American Aviation 負責建造指揮艙與服務艙—— 幾百萬個零件、層層組裝:太空船 → 艙段 → 組件 → 零件 → 原料。 這個結構天然是一棵樹:每個零件只有一個直屬上級組件。
\[ \text{太空船} \to \text{艙段} \to \text{組件} \to \text{零件} \to \text{原料}. \]

IBM 接案時最初名為 ACS,後來演變為 IMS—— 硬體基礎則是 IBM System/360(1964)與磁碟機(隨機存取,不用再倒帶)。 - 分時系統的平行線(1961): 同一年,MIT 的 CTSS(見 ../資訊科學/1961-科巴托分時系統.md)證明了 一台機器可以服務多個使用者——

\[ \text{一台電腦} \xrightarrow{\text{CTSS}} \text{多個使用者共用}. \]

IMS 把同樣的邏輯搬到資料上:一份資料,多個程式共用。

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

第一條線索:樹狀結構的數學定義#

層次模型 = 一棵有序樹 \(T = (V, E)\) : - \(V\) :記錄型態(record type)的集合——每個節點是一種記錄; - \(E \subseteq V \times V\) :父子邊——每個節點至多一個父親; - 唯一的根 \(r \in V\) :沒有父親的節點(如「太空船」)。

層次路徑(hierarchical path):從根到某節點的唯一通路——

\[ \text{path}(v) = (r, \ldots, \text{parent}(v), v). \]
\[ \boxed{\text{樹中任兩節點之間恰有一條路徑(路徑綁死)}} \]

第二條線索:父子指標遍歷#

IMS 的基本操作就是沿指標走(如同圖靈機的讀寫頭沿紙帶移動): - GET FIRST / GET NEXT:在父親的兒子序列中移動; - GET NEXT IN PARENT:跳到下一個同型態的記錄。

BOM 展開 = 樹的深度優先遍歷:

\[ \text{explode}(v) = [v] \,\Vert\, \text{explode}(c_1) \,\Vert\, \cdots \,\Vert\, \text{explode}(c_k), \]

其中 \(c_1, \ldots, c_k\) 是 \(v\) 的兒子, \(\Vert\) 是序列串接。 需要的零件總數:

\[ \text{需求量}(p) = \sum_{v \in V} [v \text{ 是 } p] \times \text{qty}(v) \times \text{需求量}(\text{parent}(v)). \]

第三條線索:資料獨立的萌芽#

IMS 的進步:程式不再讀磁帶的原始位元組,而是用「層次路徑」描述資料:

\[ \text{磁帶位元組} \xrightarrow{\text{IMS}} \text{路徑 } / \text{太空船}/\text{指令艙}/\text{降落傘}. \]

但只走了一半:路徑本身綁死在樹狀結構上—— - 樹狀結構一改,所有程式的路徑全部要改(邏輯相依); - 同一筆資料要服務兩個父親?樹說不行。

\[ \boxed{\text{子記錄只能有一個父親——這是層次模型的死穴}} \]
\[ \text{「多父親」的需求} \xrightarrow{\text{死穴}} \text{網路模型(1969)的下一案}. \]

Python:小型層次資料庫與 BOM 遞迴展開#

# IMS 層次資料庫:樹狀結構 + 父/子指標 + 物料清單(BOM)遞迴展開

class Record:
    """一筆 IMS 記錄:資料欄位 + 指向子記錄的指標(樹狀)"""
    def __init__(self, name, **fields):
        self.name = name
        self.fields = fields
        self.children = []          # 子記錄指標(父子鏈結)

    def add(self, *children):
        for c in children:
            self.children.append(c)  # 建立父子指標
        return self

def explode(rec, path=""):
    """BOM 查詢:把零件遞迴展開成完整的層次路徑"""
    full = f"{path}/{rec.name}" if path else rec.name
    results = [(full, rec.fields.get("qty", 1))]
    for c in rec.children:
        results.extend(explode(c, full))
    return results

def count_leaves(rec):
    """樹的葉節點數 = 最終的基礎零件數"""
    if not rec.children:
        return 1
    return sum(count_leaves(c) for c in rec.children)

# ---- 建立阿波羅計畫的物料清單(BOM 樹)----
bom = Record("太空船") \
    .add(
        Record("指令艙").add(
            Record("隔熱板", qty=1).add(
                Record("酚醛樹脂", qty=40),
                Record("蜂巢鋁板", qty=8),
            ),
            Record("降落傘", qty=3).add(
                Record("尼龍布", qty=12),
                Record("鋼索", qty=6),
            ),
        ),
        Record("登月艙").add(
            Record("下降引擎", qty=1).add(
                Record("噴嘴", qty=1),
                Record("燃料泵", qty=2),
            ),
            Record("起落架", qty=4).add(
                Record("緩衝柱", qty=4),
            ),
        ),
    )

# ---- 查詢 1:層次路徑遍歷( IMS 的 GET NEXT 呼叫)----
print("查詢 1:BOM 樹的層次遍歷(父 → 子)")
def walk(rec, depth=0):
    qty = rec.fields.get("qty")
    print("  " * depth + rec.name + (f"(數量={qty})" if qty else ""))
    for c in rec.children:
        walk(c, depth + 1)
walk(bom)

# ---- 查詢 2:BOM 遞迴展開 ----
print("\n查詢 2:BOM 遞迴展開(零件的完整層次路徑)")
for path, qty in explode(bom):
    print(f"  {path}(數量={qty})")

# ---- 查詢 3:統計 ----
print(f"\n查詢 3:基礎零件(葉節點)總數 = {count_leaves(bom)}")

# ---- 查詢 4:層次模型的僵化——若新資料需求破壞樹狀假設 ----
print("\n層次模型的僵化(伏筆):")
print("  同一個「尼龍布」同時供給「降落傘」與「太空服」?")
print("  樹中每個子記錄只能有一個父親 → 必須複製整條子樹,")
print("  資料重複、更新異常 → 這正是網路模型(1969)要解的案。")
輸出:
查詢 1:BOM 樹的層次遍歷(父 → 子)
太空船
  指令艙
    隔熱板(數量=1)
      酚醛樹脂(數量=40)
      蜂巢鋁板(數量=8)
    降落傘(數量=3)
      尼龍布(數量=12)
      鋼索(數量=6)
  登月艙
    下降引擎(數量=1)
      噴嘴(數量=1)
      燃料泵(數量=2)
    起落架(數量=4)
      緩衝柱(數量=4)

查詢 2:BOM 遞迴展開(零件的完整層次路徑)
  太空船(數量=1)
  太空船/指令艙(數量=1)
  太空船/指令艙/隔熱板(數量=1)
  太空船/指令艙/隔熱板/酚醛樹脂(數量=40)
  太空船/指令艙/隔熱板/蜂巢鋁板(數量=8)
  太空船/指令艙/降落傘(數量=3)
  太空船/指令艙/降落傘/尼龍布(數量=12)
  太空船/指令艙/降落傘/鋼索(數量=6)
  太空船/登月艙(數量=1)
  太空船/登月艙/下降引擎(數量=1)
  太空船/登月艙/下降引擎/噴嘴(數量=1)
  太空船/登月艙/下降引擎/燃料泵(數量=2)
  太空船/登月艙/起落架(數量=4)
  太空船/登月艙/起落架/緩衝柱(數量=4)

查詢 3:基礎零件(葉節點)總數 = 7

層次模型的僵化(伏筆):
  同一個「尼龍布」同時供給「降落傘」與「太空服」?
  樹中每個子記錄只能有一個父親 → 必須複製整條子樹,
  資料重複、更新異常 → 這正是網路模型(1969)要解的案。

結案 -- 後果與影響#

  • 第一個商用資料庫(1966/1968):
\[ \boxed{\text{IMS:資料管理的第一步——從磁帶到樹}} \]

IMS 隨阿波羅計畫上線,1968 年以 IMS/360 之名正式發售—— 這是資料庫產業的起點。 - 至今仍在運行(60 年): IMS 至今仍在銀行、航空、保險業的核心系統中運行—— ATM 提款、機票訂位,背後可能還是那棵 1961 年的樹。

\[ \text{IMS(1961)} \xrightarrow{60 \text{ 年}} \text{仍在大規模運行}. \]
  • 層次模型的僵化:
\[ \text{路徑綁死} \Longrightarrow \begin{cases} \text{結構一改,程式全改} \\ \text{多對多資料無法表示} \\ \text{資料重複、更新異常} \end{cases} \]

這些僵化為關聯式革命埋下伏筆(見 1969-巴赫曼網路模型.md、 1970-科德關聯式模型.md)。 - 樹的另一個遺產: 樹狀結構沒有消失,而是轉世——XML(1998)、JSON(2001)、檔案系統、DOM——

\[ \text{IMS 的樹} \xrightarrow{\text{轉世}} \text{階層式資料無所不在}. \]
  • 歷史定位:IMS 是資料庫史的第一章—— 它證明了「一份資料、多個程式共用」可行, 但也留下了「結構綁死」的懸案,等著 Bachman 與 Codd 來偵辦。
\[ \text{磁帶(1960)} \xrightarrow{\text{IMS(1961)}} \text{樹(1966)} \xrightarrow{\text{網路(1969)}} \text{關聯(1970)}. \]

關鍵人物與文獻#

  • Vernon Watts、Oscar Gilbert(IBM):IMS 的主要設計者(1961 起)。
  • North American Aviation / Rockwell:阿波羅計畫承包商——IMS 的第一個客戶。
  • IBM:System/360(1964)與 IMS/360(1968)——資料庫產業的起點。
  • Fernando Corbató:CTSS 分時系統(1961)——一台機器服務多人(見 ../資訊科學/1961-科巴托分時系統.md)。
  • 相關案件:../資訊科學/1936-圖靈機.md、1969-巴赫曼網路模型.md、1970-科德關聯式模型.md。