Skip to main content

Advanced Relational Design Patterns

A deep dive into relational database design patterns beyond basic normalization.
This book focuses on OLTP (Online Transaction Processing) systems, leaving OLAP (data warehousing) for another time.


Table of Contents​

  1. Fundamentals

  2. When Not to Build It Yourself

  3. Well-Known Patterns

  4. Lesser-Known / Advanced Patterns

  5. Appendices


Fundamentals​

Bridge Tables​

Purpose: Implement many-to-many relationships between entities.
TODO: Add code example + when to include additional attributes.

Surrogate vs Natural Keys​

Purpose: Trade-offs between business-defined keys and generated keys.
TODO: Add pros/cons table + sample schemas.

Foreign Key Constraints​

Purpose: Enforce referential integrity.
TODO: Add cascading vs restricted delete/update scenarios.

Normalization & Denormalization​

Purpose: Ensure data integrity while balancing performance.
TODO: Show normalized vs denormalized schema comparisons.

ON DELETE / ON UPDATE Behaviors​

Purpose: Define behavior when referenced rows are updated/deleted.
TODO: Cover CASCADE, SET NULL, RESTRICT.


When Not to Build It Yourself​

TOAST (Postgres Overflow Storage)​

Purpose: Automatically handles oversized column values (e.g., large text or JSON) without manual overflow tables.
TODO: Show how this works behind the scenes.

Clustered & Index-Organized Tables​

Purpose: Store rows in index order for faster lookups, removing need for custom ordered child tables.
TODO: Compare SQL Server clustered indexes vs Oracle index-organized tables.

MVCC Row Versioning​

Purpose: Allows concurrent reads/writes via row versioning, often replacing DIY version tables for transactional consistency.
TODO: Explain row versions and vacuuming.

Materialized Views​

Purpose: Pre-computed join or aggregation results handled natively.
TODO: Contrast with DIY summary tables.

Partial & Expression Indexes​

Purpose: Optimize queries on data subsets or derived values without separate filtered tables.
TODO: Show index syntax and performance impact.

Computed Columns​

Purpose: Derived columns calculated by the DB engine, avoiding stored procedures for periodic sync of summary values.
TODO: Example persisted vs non-persisted computed columns.

Automatic Partitioning & Sharding​

Purpose: Distribute data transparently instead of building custom sharding logic.
TODO: Discuss native implementations (e.g., Postgres declarative partitioning).

Purpose: Native search capabilities (Postgres tsvector, SQL Server Full-Text).
TODO: Avoid building custom search indexing tables.

Row-Level Security (RLS)​

Purpose: Apply row-specific access rules at the database level.
TODO: Example: Postgres RLS policies vs manual filtering logic.


Well-Known Patterns​

EAV (Entity-Attribute-Value)​

Purpose: Flexible schema for variable attributes.
TODO: Example schema + pros/cons.

RBAC & ABAC​

Purpose: Role-based and attribute-based access control.
TODO: Example schemas for each.

Object-Level Access Control (OLAC)​

Purpose: Control access at a per-object or per-record level.
Challenges:

  • Permutational explosion: users × entities × records × CRUD permissions can grow quickly.
  • Performance: index-based lookups can still be efficient (O(log n)), but data volume and write churn must be considered.

Patterns:

  • Ownership Column: one owner per row, simple filter.
  • Access Control List (ACL) Table: multiple users per object with explicit permissions.
  • Group-Based ACL: assign permissions to groups, then map users to groups.
  • Hybrid (RBAC + ACL): role defaults + explicit overrides.
  • Inherited Permissions: derive from parent objects to avoid duplicate rows.

DB Built-in Alternative: Row-Level Security (see When Not to Build It Yourself).

TODO: Add schema examples for each approach + indexing recommendations.

Soft Deletes​

Purpose: Logical deletion without physical row removal.
TODO: Add pattern variants.

Audit Logging​

Purpose: Track changes to rows over time.
TODO: Example with triggers vs application logic.

Multi-Tenancy​

Purpose: Separate or shared schemas for multiple customers.
TODO: Compare design trade-offs.

Recursive Trees​

Purpose: Represent hierarchical data.
TODO: Compare adjacency list, nested sets, closure table.


Lesser-Known / Advanced Patterns​

Self-Referencing Bridge Table​

Purpose: Represent relationships between rows of the same entity (e.g., user friendships).
TODO: Example schema + handling directionality.

Polymorphic Associations Without Explicit FK Constraints​

Purpose: Link a single table to multiple entity types without strict referential integrity.
TODO: Discuss safety trade-offs and indexing.

Dynamic Attribute Modeling​

Purpose: Mix structured columns and flexible JSON attributes.
TODO: Show hybrid schema example.

Conditional Relationships​

Purpose: Model mutually exclusive relationships (e.g., A belongs to B or C, not both).
TODO: Implementation strategies.

Versioned Data (SCD Type 2)​

Purpose: Keep historical row versions while allowing current active state.
TODO: Example schema + query patterns.

Split Relations​

Purpose: Break wide tables into optional 1:0-1 relationships.
TODO: Performance trade-offs.

Type Tables & Inheritance Modeling​

Purpose: Represent class hierarchies in relational models.
TODO: Compare single-table vs class-table inheritance.


Appendices​

SQL DDL Examples​

TODO: Provide SQL for every pattern.

Performance & Indexing Notes​

TODO: Summarize indexing strategies.

Migration Strategies​

TODO: Discuss refactoring schemas without downtime.

Testing Relational Logic​

TODO: Strategies for testing constraints and relational integrity.


Future Exploration​

This book focuses on schema patterns and built-in features.
A future volume or video series will explore OLAC implementations in depth, including:

  • Row-Level Security vs manual ACL approaches
  • Permission caching strategies
  • Performance benchmarks on large-scale datasets

Comments

No comments yet. Be the first!