Chapter 14 · Time, History, Hierarchies, and Recursive Structures

Nested Sets, Materialized Paths, and Closure Tables

Compare nested sets, materialized paths, and closure tables for hierarchy workloads, including read/write tradeoffs, subtree queries, ancestor queries, and maintenance.

Beginner75–105 minutesHierarchy alternatives + closure tablesLast reviewed: August 2026

Learning outcomes

Adjacency lists are flexible, but some workloads need very fast subtree or ancestor queries. Alternative hierarchy representations—nested sets, materialized paths, and closure tables—trade additional storage or write complexity for cheaper reads.

01

Understand nested-set interval encoding.

02

Understand materialized path encoding and path queries.

03

Understand closure-table ancestor/descendant pairs.

04

Select a hierarchy model from workload characteristics.

Nested sets

Each node receives left/right bounds:

model · example
Mechanical   lft=1  rgt=8Bearing      lft=2  rgt=3Seal         lft=4  rgt=5Alignment    lft=6  rgt=7

A descendant has bounds inside its ancestor's interval.

Subtree query

sql · example
SELECT child.*FROM category parentJOIN category child  ON child.lft BETWEEN parent.lft AND parent.rgtWHERE parent.category_id = ?;

Subtree reads can be very efficient.

Nested-set write cost

Inserting or moving nodes may require renumbering many left/right values. This makes nested sets better for read-mostly, relatively static trees.

Materialized path

Store a path:

model · example
/mechanical/bearing/mechanical/seal/electrical/sensor

or an ID path:

model · example
/12/18/44/

Path-prefix queries

Descendants of node path /12/18/ are rows whose path begins with that prefix.

Materialized-path advantages

  • simple path rendering;
  • fast subtree prefix queries with suitable indexing;
  • easy depth calculation in some designs;
  • human-readable paths if codes are used.

Materialized-path disadvantages

Moving a subtree requires updating path values for the node and all descendants. Path encoding also needs escaping/delimiter rules if user-facing codes appear in the path.

Closure table

Store every ancestor/descendant relationship:

model · example
CategoryClosure(  ancestor_id,  descendant_id,  depth)

Each node usually includes a self-row at depth 0.

Closure example

model · example
ancestor   descendant   depthA          A            0A          B            1A          C            2B          B            0B          C            1C          C            0

Ancestor query

sql · example
SELECT ancestor_id, depthFROM category_closureWHERE descendant_id = ?ORDER BY depth DESC;

Descendant query

sql · example
SELECT descendant_id, depthFROM category_closureWHERE ancestor_id = ?;

Closure-table cost

For a chain of N nodes, closure rows can approach \(N(N+1)/2\). Balanced trees are less extreme, but storage still exceeds one row per node.

Closure-table write maintenance

Inserting a node requires closure rows linking all ancestors to the new node. Moving a subtree is more complex because old transitive relationships must be removed and new ones inserted.

Why closure tables are powerful

  • ancestor queries are simple;
  • descendant queries are simple;
  • depth is explicit;
  • cycle detection can be easier;
  • recursive SQL may be unnecessary for common reads.
Tradeoff

Closure tables precompute transitive relationships: more storage and maintenance in exchange for very cheap hierarchy reads.

Comparison

ModelReadsMovesStorage
Adjacency listRecursiveEasyLow
Nested setsVery fast subtreeExpensiveLow
Materialized pathFast prefixUpdate subtree pathsMedium
Closure tableVery fast ancestors/descendantsComplexHigh

Hybrid designs

A system may keep adjacency parent_id as the canonical structure and maintain a materialized path or closure table as a derived acceleration structure. That adds synchronization duties but preserves a simple source representation.

WorkshopHub choice examples

  • Failure categories changing occasionally: adjacency list or materialized path.
  • Large read-heavy equipment taxonomy: closure table may help.
  • Mostly static publication taxonomy: nested sets can work.
  • Frequently reorganized teams: adjacency list is often preferable.

Practice: choose a hierarchy model

Product taxonomy

A taxonomy has 2 million nodes, subtree reads are extremely frequent, moves are rare, and ancestor breadcrumbs are common. Which models are worth considering?

Review answer

Closure table and materialized path are strong candidates because they accelerate descendant/ancestor access. Nested sets may also work for highly static trees. Benchmark storage and move costs against the workload.

Summary and next lesson

Hierarchy models make different tradeoffs. Adjacency lists optimize simplicity and moves; nested sets optimize static subtree reads; materialized paths optimize path/prefix access; closure tables precompute transitive reachability. The final lesson expands beyond trees into general graph-like relationships.

References

  • Joe Celko, Trees and Hierarchies in SQL for Smarties.
  • Bill Karwin, SQL Antipatterns.
  • Database vendor documentation for recursive queries and path/index support.

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only assets compatible with the Ethereum/ERC-20 network. Do not send TRC-20/TRON assets.