Dependency Preserving Decomposition
π‘ Core Intuitionβ
π³ The Everyday Analogy: The Split Contract and Cross-Town Verificationβ
Imagine a business contract between three parties: Supplier (), Logistics (), and Retailer (). The contract holds two foundational legal rules:
- Whenever Supplier delivers goods, Logistics must assign a transit vehicle ().
- Whenever Logistics assigns a vehicle, Retailer must reserve warehouse bay space ().
From these two rules, you can logically infer a third guarantee: whenever Supplier delivers, warehouse space is eventually reserved ().
Now suppose the business archives these records by splitting paperwork into two branch offices:
- Branch 1 holds records of and enforces Rule 1 ().
- Branch 2 holds records of and enforces Rule 2 ().
Can the business enforce all original contract rules? Yes! Whenever a delivery occurs at Branch 1, it checks locally. When Branch 2 receives the handover, it checks locally. The overarching guarantee () is satisfied automatically through the chain without anyone having to travel across town to cross-examine both offices simultaneously. This is Dependency Preservation.
If a decomposition forces you to run across town (execute expensive cross-table joins) just to verify that a simple rule has not been broken, the decomposition has failed to preserve dependencies.
π» Bridging to Computer Scienceβ
In database decomposition, Lossless Join ensures that data is not fabricated or corrupted. Dependency Preservation ensures that integrity constraints can be enforced cheaply and locally.
Original Schema R with FD set F
Decomposed into: { R1 with F1, R2 with F2, ..., Rk with Fk }
Dependency Preserved iff: (F1 βͺ F2 βͺ ... βͺ Fk)+ === F+
While lossless join is strictly mandatory in database architecture, dependency preservation is desirable but optional. A schema decomposition that does not preserve dependencies can still be deployed, but enforcing cross-relation rules requires expensive application-level checks or cross-table join triggers.
π Core Deep-Dive & Conceptsβ
Formal Definition of Dependency Preservationβ
Let relation schema with functional dependency set be decomposed into sub-relations .
For each sub-relation , its projected functional dependency set is the set of all dependencies such that all attributes in belong exclusively to :
The decomposition is Dependency Preserving if and only if the closure of the union of all projected dependencies is identical to the closure of the original dependency set:
In practical terms, this means every single dependency must be either:
- Directly covered: Entirely contained within the attribute set of at least one single decomposed sub-relation (), OR
- Derivable (Inferred): Logically deducible from the projected dependencies of the sub-relations using Armstrong's Axioms.
Why Dependency Preservation Mattersβ
The primary purpose of dependency preservation is runtime performance and constraint enforcement:
- Local Constraint Enforcement: When an application executes an
INSERTorUPDATEon sub-relation , the database engine can verify all applicable functional dependencies using local indexes on in or time. - Zero Inter-Relational Joins: If a dependency is NOT preserved, verifying whether a new row violates requires executing a natural join across multiple tables () before every write operationβa prohibitive performance bottleneck.
Step-by-Step Dependency Preservation Testing Algorithmβ
Computing the full exponential closure and projecting it onto every is computationally expensive (). In relational engineering, we use an efficient polynomial-time testing algorithm:
To test whether a specific functional dependency is preserved across decomposition :
- Initialize result attribute set:
- Repeat until no longer changes:
- For each sub-relation :
- Compute the intersection of current set with :
- Compute the attribute closure of under the original dependency set :
- Intersect this closure back with :
- Add these newly derived attributes to :
- For each sub-relation :
- If , then the functional dependency is preserved.
- Repeat this check for every dependency in . If all dependencies in are preserved, the entire decomposition is Dependency Preserving.
Comprehensive Mathematical Examplesβ
Example 1: Full Dependency Preservationβ
Consider relation with functional dependencies:
Decompose into:
Let us determine the projected dependencies:
-
For :
- is directly present in .
- Does hold? Compute under : . Since , holds in , and both . Therefore, .
-
For :
- is directly present in .
- Does hold? Compute under : . Since , holds in , and both . Therefore, .
-
Check Original Dependencies under :
- : Directly in .
- : Directly in .
- : In , we have (from ) and (from ). By transitivity:
All original functional dependencies are fully derived. The decomposition is Dependency Preserving!
Example 2: Non-Preserving BCNF Decompositionβ
Consider relation with:
Candidate keys:
In , is not a superkey, which violates BCNF. To convert to BCNF, decompose along :
- For :
- Projected FD: .
- For :
- Projected FDs: Only trivial FDs hold ().
- Check Original Dependency under :
- Compute closure of under :
- Attribute cannot be derived!
- is LOST.
This decomposition is Lossless (since and makes a key of ), but it is NOT Dependency Preserving.
Core Structural Theorems of Normalization & Dependenciesβ
The following foundational theorems govern normal form transformations:
-
The 3NF Dual Guarantee: For any relation schema and functional dependency set , there always exists a decomposition into 3NF that is simultaneously Lossless and Dependency Preserving.
-
The BCNF Trade-Off: For any relation schema and functional dependency set , there always exists a Lossless decomposition into BCNF, but dependency preservation cannot always be guaranteed.
-
Composite Key Constraint in BCNF vs. 4NF: A relation schema will necessarily possess a composite candidate key if is in BCNF but violates 4NF.
-
Simple Key Progression Theorems:
- If relation is in 3NF and every candidate key of is simple (single-attribute), then is guaranteed to be in BCNF.
- If relation is in BCNF and has at least one simple candidate key, then is guaranteed to be in 4NF.
- If relation is in 3NF and every candidate key is simple, then is guaranteed to be in 5NF.
π Architecture / Visual Blueprintβ
The following flow represents the structural trade-off between Lossless Join and Dependency Preservation during normalization decomposition:
π In The Real World: Production Case Studyβ
Distributed Microservice Architecture: Preserving FDs Across Databasesβ
A multi-tenant SaaS healthcare platform handles doctor appointments across clinics.
The Unified Medical Schemaβ
Business Rules:
- A patient cannot be in two different clinics at the same slot time:
- A doctor belongs to a single primary clinic:
The Distributed Refactoring Trapβ
The engineering team separates scheduling from provider management:
Doctor_Service_DB:Booking_Service_DB:
Notice that the dependency is lost across the service boundary!
The Consequenceβ
When Patient #404 books an appointment with Doctor Alpha at 10:00 AM in Clinic East, and simultaneously books an appointment with Doctor Beta at 10:00 AM in Clinic West, Booking_Service_DB accepts both bookings because each booking involves a different doctor.
To prevent this double-booking, the application is forced to implement a two-phase distributed commit protocol (2PC) or an event-driven saga join query across network microservices on every booking attempt, increasing latency from to .
Maintaining a schema that preserved the dependency would have allowed the database to enforce the rule locally using a composite unique index in time.
π― Exam & Interview Pitfall Checkβ
Question 1: Relation with functional dependencies: is decomposed into , , and . Determine whether this decomposition is dependency preserving.
Answer:
- Determine projected dependencies:
- For : .
- For : .
- For : .
- Check the remaining original dependency :
From the union :
- Compute closure of under :
- Attribute cannot be reached because no dependency in has on the left-hand side!
- Therefore, cannot be derived from the projected dependencies.
- The decomposition is NOT Dependency Preserving.
Question 2: Explain the operational distinction between a decomposition being Lossless versus being Dependency Preserving.
Answer:
- Lossless Join is a structural data integrity property. It guarantees that the natural join of decomposed relations reconstructs the exact original relation without missing rows and without generating spurious tuples. Violating lossless join results in data corruption upon querying.
- Dependency Preservation is an operational performance property. It guarantees that all functional dependencies can be verified on individual decomposed relations without performing joins across multiple tables. Violating dependency preservation does not cause data loss, but forces the system to perform costly cross-table joins during write transactions to enforce business rules.
Trap 1: Believing that a dependency is preserved only if its exact left and right hand attributes exist in the same sub-relation. A dependency is preserved even if it does not appear directly in any single sub-relation, provided it can be logically deduced (via transitive closure) from the union of projected dependencies across the sub-relations.
Trap 2: Assuming that BCNF decomposition is always preferred over 3NF. In production database design, if a BCNF decomposition sacrifices a critical functional dependency, 3NF is frequently preferred. 3NF guarantees both lossless join and complete dependency preservation, avoiding distributed validation joins on every write.