Jaco van der Laan

Join Reordering & Structural Optimization — When Metadata Becomes an Optimization Surface

19/02/2026  ·  Data Engineering  ·  Metadata  ·  SQL Code Generation

metadata sql
‹ ›

Structural normalization and determinism


Join Reordering & Structural Optimization — When Metadata Becomes an Optimization Surface

Structural normalization and determinism

SQL optimizers inside databases already reorder joins.

So why would a metadata-driven framework care?

Because there are two very different concerns:

  1. Runtime execution optimization (handled by the database engine)
  2. Structural normalization and determinism (handled by MDDE)

These are not the same problem.

MDDE does not attempt to replace the database optimizer.

It ensures that the structural representation of joins is:

  • Explicit
  • Deterministic
  • Canonical
  • Traceable

Before SQL ever reaches execution.


The Structural Problem

In real systems, equivalent queries are often written differently:

FROM orders o  
JOIN customers c ON o.customer_id = c.id  
JOIN order_items oi ON oi.order_id = o.id

vs

FROM order_items oi  
JOIN orders o ON oi.order_id = o.id  
JOIN customers c ON o.customer_id = c.id

These are logically equivalent.

But structurally different.

Which means:

  • Lineage graphs differ
  • Canonical SQL differs
  • Diffs become noisy
  • Optimizer diagnostics become unstable

MDDE aims for structural determinism.


Canonical Join Ordering

When SQL is parsed, joins are represented as relationship metadata:

metadata.relationship  
metadata.entity_mapping

Each relationship has:

  • Parent entity
  • Child entity
  • Join condition
  • Join type
  • Cardinality (when available)

Instead of preserving textual order, MDDE builds a join graph.

Then applies deterministic ordering rules.


Deterministic Ordering Strategy

A simple canonical rule might be:

  1. Root entity first
  2. Then breadth-first expansion
  3. Alphabetical fallback for ties

Example canonical output:

FROM customers c  
JOIN orders o ON o.customer_id = c.id  
JOIN order_items oi ON oi.order_id = o.id

This ensures:

  • Stable regeneration
  • Clean diffs
  • Predictable lineage
  • Deterministic SQL

The goal is not runtime optimization.

The goal is structural stability.


Join Graph Modeling

Join structure is represented internally as a graph:

Nodes:

  • Entities

Edges:

  • Relationships

Example query:

customers  
   │  
   └── orders  
           │  
           └── order_items

MDDE stores this as relational metadata.

Then generates join order based on graph traversal.


Cost-Based Hints (Optional Layer)

MDDE can optionally incorporate:

  • Relationship cardinality
  • Known primary/foreign keys
  • Join selectivity metadata
  • Historical row count statistics

Not to replace the database optimizer.

But to:

  • Detect problematic patterns
  • Flag cross joins
  • Identify fan-out explosions
  • Suggest safer join anchors

Example diagnostic:

SELECT *  
FROM metadata.optimizer_diagnostics  
WHERE pass_name = 'join_analysis';

Output:

Structural awareness improves architectural quality.


Avoiding Semantic Drift

Join reordering must be safe.

MDDE does not reorder joins when:

  • Outer joins are involved in unsafe positions
  • Window functions depend on join order
  • Filter placement changes semantics

Semantic protection rules are embedded in optimizer passes.

Reordering is only applied when provably equivalent.


Why This Matters in Migration

In migration programs:

  • Equivalent SQL is often rewritten
  • Join order changes create noise
  • Reviewers struggle with diff overload
  • Structural drift hides logical drift

Canonical join ordering eliminates cosmetic differences.

It isolates real semantic changes.

That reduces migration risk.


🔧 Technical Deep Dive

Inspect Join Graph

SELECT  
    parent.entity_name AS parent,  
    child.entity_name  AS child,  
    r.join_condition  
FROM metadata.relationship r  
JOIN metadata.entity parent  
  ON r.parent_entity_id = parent.entity_id  
JOIN metadata.entity child  
  ON r.child_entity_id = child.entity_id  
WHERE parent.model_id = 'mdl_sales';

Detect Potential Many-to-Many Joins

SELECT *  
FROM metadata.relationship  
WHERE cardinality = 'many-to-many';

Regenerate Canonical SQL

python -m mdde.scripts.export_model mdl_sales --canonical

Closing

Databases optimize execution.

MDDE optimizes structure.

When structure is deterministic:

  • Diffs are clean
  • Reviews are faster
  • Lineage is stable
  • Governance is reliable

Optimization begins before runtime.

It begins in metadata.