閉包テーブルとは?階層データを高速・柔軟に扱うためのデータベース設計手法をわかりやすく解説【RDBでツリー構造を扱う】

フォルダ階層、カテゴリ分類、組織図、メニュー構造など、**ツリー状のデータ(階層構造)**をデータベースで管理したい場面は多くあります。
しかし、リレーショナルデータベース(RDB)では階層構造の取り扱いが苦手です。

そこで登場するのが 閉包テーブル(Closure Table) という設計手法です。
閉包テーブルを使うと、階層データを高速・柔軟に扱うことができ、大規模データでも効率よく構造を維持できます。

この記事では、閉包テーブルとは何か、メリット、使いどころ、具体的なデータ構造まで初心者にもわかりやすく解説します。


◆ 閉包テーブルとは?

閉包テーブル(Closure Table)とは、
階層構造(親子関係)を持つデータの全ての祖先・子孫関係を別テーブルに保存する方法
のことです。

つまり、「親 → 子」だけでなく、
親 → 孫、親 → 曾孫 など “すべての関係” を記録する のが特徴です。


◆ 階層構造を表すデータベース方式の中での位置づけ

階層データの管理には複数の方法があります。

方式特徴
隣接リスト方式(Adjacency List)単純だが階層検索が遅い
経路列挙方式(Path Enumeration)経路を文字列で保存、更新が大変
入れ子集合(Nested Set)読み取りは速いが更新が重い
閉包テーブル(Closure Table)読み取り・更新どちらも柔軟で高速

閉包テーブルは 読み取り・更新のバランスが最も良い方式 とされ、多くのシステムで採用されています。


◆ 閉包テーブルの基本構造

閉包テーブル方式では、次の2つのテーブルを用います。


● 1. ノード(実体)テーブル

例:カテゴリテーブル

id | name
-----------
1  | 家電
2  | テレビ
3  | 液晶テレビ

● 2. 閉包テーブル(祖先・子孫関係を格納)

閉包テーブルの例:

ancestor | descendant | depth
--------------------------------
1        | 1          | 0
1        | 2          | 1
1        | 3          | 2
2        | 2          | 0
2        | 3          | 1
3        | 3          | 0

● depth

  • 0 = 自分自身
  • 1 = 直接の子
  • 2 = 孫
  • それ以上 = 子孫関係

このように、階層の「全ての経路」を保存します。


◆ 閉包テーブルのメリット

● 1. 階層検索が高速

「あるノードのすべての子や孫を取得」
「すべての親階層を一覧表示」
などが 1クエリで可能。


● 2. 木構造の再構成が容易

階層構造を復元するための計算が簡単。


● 3. 更新操作が柔軟

  • 子ノードの追加
  • 親ノードの変更
  • サブツリーの移動

などが比較的低コストで行える。


● 4. 入れ子集合方式より圧倒的に扱いやすい

入れ子集合は更新が重いが、閉包テーブルは変更に強い。


◆ 閉包テーブルのデメリット

  • 関係数が多いほどテーブルが肥大化する
  • データの追加・削除には複数行の更新が発生する
  • 小規模データにはオーバースペックになりがち

しかし、階層が深い大規模データでは非常に有用です。


◆ 閉包テーブルはどこで使われる?

● 大規模カテゴリ管理

  • ECサイトの商品カテゴリ
  • メニュー構造
  • コンテンツ管理システム(CMS)

● 組織図

複雑な部署や階層の構造管理に合う。

● フォルダツリー

ファイル管理・権限管理システムなど。

● グラフ構造

祖先・子孫の関係が曖昧な複雑グラフにも応用される。


◆ 閉包テーブルのクエリ例(SQL)

● すべての子孫を取得

SELECT descendant 
FROM closure_table 
WHERE ancestor = 1;

● すべての親階層を取得

SELECT ancestor 
FROM closure_table 
WHERE descendant = 3;

◆ 他の階層管理方式との比較まとめ

方式読み取り更新データ量特徴
隣接リスト遅い速い小さい単純
経路列挙速い遅い経路管理が必要
入れ子集合速い非常に遅い読取最速
閉包テーブル速い大きい読取と更新のバランス最良

◆ まとめ:閉包テーブルは階層データ管理の決定版

閉包テーブルは、

  • 階層データのすべての親子関係を保存
  • 読み取りが高速
  • サブツリーの移動も容易
  • 大規模かつ深い階層に対応
  • 隣接リスト・入れ子集合より柔軟

という特徴を持ち、階層構造を扱うデータベース設計として非常に優秀です。