Skip to main content

Dependency Preserving Decomposition

πŸ“šModule 01Topic 1.1⏱️5 min read
🎯High-Yield For:Semester Exams β€’ GATE CSE β€’ Technical Interviews

πŸ’‘ Core Intuition​

🍳 The Everyday Analogy: The Split Contract and Cross-Town Verification​

Imagine a business contract between three parties: Supplier (AA), Logistics (BB), and Retailer (CC). The contract holds two foundational legal rules:

  1. Whenever Supplier AA delivers goods, Logistics BB must assign a transit vehicle (A→BA \to B).
  2. Whenever Logistics BB assigns a vehicle, Retailer CC must reserve warehouse bay space (B→CB \to C).

From these two rules, you can logically infer a third guarantee: whenever Supplier AA delivers, warehouse space is eventually reserved (A→CA \to C).

Now suppose the business archives these records by splitting paperwork into two branch offices:

  • Branch 1 holds records of (A,B)(A, B) and enforces Rule 1 (Aβ†’BA \to B).
  • Branch 2 holds records of (B,C)(B, C) and enforces Rule 2 (Bβ†’CB \to C).

Can the business enforce all original contract rules? Yes! Whenever a delivery occurs at Branch 1, it checks A→BA \to B locally. When Branch 2 receives the handover, it checks B→CB \to C locally. The overarching guarantee (A→CA \to C) 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 RR with functional dependency set FF be decomposed into sub-relations D={R1,R2,…,Rk}D = \{R_1, R_2, \dots, R_k\}.

For each sub-relation RiR_i, its projected functional dependency set FiF_i is the set of all dependencies Xβ†’Y∈F+X \to Y \in F^+ such that all attributes in XβˆͺYX \cup Y belong exclusively to RiR_i: Fi=Ξ Ri(F)={Xβ†’Y∈F+∣(XβˆͺY)βŠ†Ri}F_i = \Pi_{R_i}(F) = \{ X \to Y \in F^+ \mid (X \cup Y) \subseteq R_i \}

The decomposition DD 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: (F1βˆͺF2βˆͺβ‹―βˆͺFk)+=F+(F_1 \cup F_2 \cup \dots \cup F_k)^+ = F^+

In practical terms, this means every single dependency Xβ†’Y∈FX \to Y \in F must be either:

  1. Directly covered: Entirely contained within the attribute set of at least one single decomposed sub-relation RiR_i (XβˆͺYβŠ†RiX \cup Y \subseteq R_i), OR
  2. 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 INSERT or UPDATE on sub-relation RiR_i, the database engine can verify all applicable functional dependencies using local indexes on RiR_i in O(1)O(1) or O(log⁑n)O(\log n) time.
  • Zero Inter-Relational Joins: If a dependency Xβ†’YX \to Y is NOT preserved, verifying whether a new row violates Xβ†’YX \to Y requires executing a natural join across multiple tables (R1β‹ˆR2R_1 \bowtie R_2) before every write operationβ€”a prohibitive performance bottleneck.

Step-by-Step Dependency Preservation Testing Algorithm​

Computing the full exponential closure F+F^+ and projecting it onto every RiR_i is computationally expensive (O(2n)O(2^n)). In relational engineering, we use an efficient polynomial-time testing algorithm:

To test whether a specific functional dependency Xβ†’Y∈FX \to Y \in F is preserved across decomposition {R1,R2,…,Rk}\{R_1, R_2, \dots, R_k\}:

  1. Initialize result attribute set: Z=XZ = X
  2. Repeat until ZZ no longer changes:
    • For each sub-relation RiR_i:
      • Compute the intersection of current set ZZ with RiR_i: I=Z∩RiI = Z \cap R_i
      • Compute the attribute closure of II under the original dependency set FF: I+I^+
      • Intersect this closure back with RiR_i: Ci=I+∩RiC_i = I^+ \cap R_i
      • Add these newly derived attributes to ZZ: Z=ZβˆͺCiZ = Z \cup C_i
  3. If YβŠ†ZY \subseteq Z, then the functional dependency Xβ†’YX \to Y is preserved.
  4. Repeat this check for every dependency in FF. If all dependencies in FF are preserved, the entire decomposition is Dependency Preserving.

Comprehensive Mathematical Examples​

Example 1: Full Dependency Preservation​

Consider relation R(A,B,C)R(A, B, C) with functional dependencies: F={A→B,B→C,C→A}F = \{ A \to B, \quad B \to C, \quad C \to A \}

Decompose into: R1(A,B)andR2(B,C)R_1(A, B) \quad \text{and} \quad R_2(B, C)

Let us determine the projected dependencies:

  1. For R1(A,B)R_1(A, B):

    • Aβ†’BA \to B is directly present in R1R_1.
    • Does Bβ†’AB \to A hold? Compute (B)+(B)^+ under FF: (B)+={B,C,A}(B)^+ = \{B, C, A\}. Since A∈(B)+A \in (B)^+, Bβ†’AB \to A holds in F+F^+, and both B,A∈R1B, A \in R_1. Therefore, F1={Aβ†’B,Bβ†’A}F_1 = \{ A \to B, \quad B \to A \}.
  2. For R2(B,C)R_2(B, C):

    • Bβ†’CB \to C is directly present in R2R_2.
    • Does Cβ†’BC \to B hold? Compute (C)+(C)^+ under FF: (C)+={C,A,B}(C)^+ = \{C, A, B\}. Since B∈(C)+B \in (C)^+, Cβ†’BC \to B holds in F+F^+, and both C,B∈R2C, B \in R_2. Therefore, F2={Bβ†’C,Cβ†’B}F_2 = \{ B \to C, \quad C \to B \}.
  3. Check Original Dependencies under Fβ€²=F1βˆͺF2F' = F_1 \cup F_2:

    • Aβ†’BA \to B: Directly in F1F_1. βœ“\checkmark
    • Bβ†’CB \to C: Directly in F2F_2. βœ“\checkmark
    • Cβ†’AC \to A: In Fβ€²F', we have Cβ†’BC \to B (from F2F_2) and Bβ†’AB \to A (from F1F_1). By transitivity: Cβ†’BandBβ†’Aβ€…β€ŠβŸΉβ€…β€ŠCβ†’Aβœ“C \to B \quad \text{and} \quad B \to A \implies C \to A \quad \checkmark

All original functional dependencies are fully derived. The decomposition is Dependency Preserving!


Example 2: Non-Preserving BCNF Decomposition​

Consider relation R(A,B,C)R(A, B, C) with: F={AB→C,C→B}F = \{ AB \to C, \quad C \to B \}

Candidate keys: (AB)+={A,B,C}β€…β€ŠβŸΉβ€…β€ŠCK1={AB}(AB)^+ = \{A, B, C\} \implies CK_1 = \{AB\} (AC)+={A,C,B}β€…β€ŠβŸΉβ€…β€ŠCK2={AC}(AC)^+ = \{A, C, B\} \implies CK_2 = \{AC\}

In C→BC \to B, CC is not a superkey, which violates BCNF. To convert to BCNF, decompose along C→BC \to B: R1(B,C)andR2(A,C)R_1(B, C) \quad \text{and} \quad R_2(A, C)

  1. For R1(B,C)R_1(B, C):
    • Projected FD: F1={Cβ†’B}F_1 = \{ C \to B \}.
  2. For R2(A,C)R_2(A, C):
    • Projected FDs: Only trivial FDs hold (F2=βˆ…F_2 = \emptyset).
  3. Check Original Dependency ABβ†’CAB \to C under Fβ€²=F1βˆͺF2={Cβ†’B}F' = F_1 \cup F_2 = \{ C \to B \}:
    • Compute closure of ABAB under Fβ€²F': (AB)Fβ€²+={A,B}(AB)_{F'}^+ = \{A, B\}
    • Attribute CC cannot be derived!
    • Cβˆ‰(AB)Fβ€²+β€…β€ŠβŸΉβ€…β€ŠABβ†’CC \notin (AB)_{F'}^+ \implies AB \to C is LOST.

This decomposition is Lossless (since R1∩R2={C}R_1 \cap R_2 = \{C\} and Cβ†’BC \to B makes CC a key of R1R_1), but it is NOT Dependency Preserving.


Core Structural Theorems of Normalization & Dependencies​

The following foundational theorems govern normal form transformations:

  1. The 3NF Dual Guarantee: For any relation schema RR and functional dependency set FF, there always exists a decomposition into 3NF that is simultaneously Lossless and Dependency Preserving.

  2. The BCNF Trade-Off: For any relation schema RR and functional dependency set FF, there always exists a Lossless decomposition into BCNF, but dependency preservation cannot always be guaranteed.

  3. Composite Key Constraint in BCNF vs. 4NF: A relation schema RR will necessarily possess a composite candidate key if RR is in BCNF but violates 4NF.

  4. Simple Key Progression Theorems:

    • If relation RR is in 3NF and every candidate key of RR is simple (single-attribute), then RR is guaranteed to be in BCNF.
    • If relation RR is in BCNF and has at least one simple candidate key, then RR is guaranteed to be in 4NF.
    • If relation RR is in 3NF and every candidate key is simple, then RR 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​

Appointments(Patient_ID,Clinic_ID,Doctor_ID,Slot_Time)\text{Appointments}(\text{Patient\_ID}, \text{Clinic\_ID}, \text{Doctor\_ID}, \text{Slot\_Time})

Business Rules:

  1. A patient cannot be in two different clinics at the same slot time: (Patient_ID,Slot_Time)β†’Clinic_ID(\text{Patient\_ID}, \text{Slot\_Time}) \to \text{Clinic\_ID}
  2. A doctor belongs to a single primary clinic: Doctor_ID→Clinic_ID\text{Doctor\_ID} \to \text{Clinic\_ID}

The Distributed Refactoring Trap​

The engineering team separates scheduling from provider management:

  • Doctor_Service_DB: (Doctor_IDβ€Ύ,Clinic_ID)(\underline{\text{Doctor\_ID}}, \text{Clinic\_ID})
  • Booking_Service_DB: (Patient_ID,Doctor_ID,Slot_Timeβ€Ύ)(\underline{\text{Patient\_ID}, \text{Doctor\_ID}, \text{Slot\_Time}})

Notice that the dependency (Patient_ID,Slot_Time)β†’Clinic_ID(\text{Patient\_ID}, \text{Slot\_Time}) \to \text{Clinic\_ID} 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 5Β ms5\text{ ms} to 220Β ms220\text{ ms}.

Maintaining a schema that preserved the dependency would have allowed the database to enforce the rule locally using a composite unique index in O(log⁑n)O(\log n) time.


🎯 Exam & Interview Pitfall Check​

Core Conceptual Questions

Question 1: Relation R(A,B,C,D)R(A, B, C, D) with functional dependencies: F={A→B,B→C,C→D,D→A}F = \{ A \to B, \quad B \to C, \quad C \to D, \quad D \to A \} is decomposed into R1(A,B)R_1(A, B), R2(B,C)R_2(B, C), and R3(C,D)R_3(C, D). Determine whether this decomposition is dependency preserving.

Answer:

  1. Determine projected dependencies:
    • For R1(A,B)R_1(A, B): Aβ†’B∈F1A \to B \in F_1.
    • For R2(B,C)R_2(B, C): Bβ†’C∈F2B \to C \in F_2.
    • For R3(C,D)R_3(C, D): Cβ†’D∈F3C \to D \in F_3.
  2. Check the remaining original dependency Dβ†’AD \to A: From the union Fβ€²=F1βˆͺF2βˆͺF3={Aβ†’B,Bβ†’C,Cβ†’D}F' = F_1 \cup F_2 \cup F_3 = \{ A \to B, \quad B \to C, \quad C \to D \}:
    • Compute closure of DD under Fβ€²F': (D)Fβ€²+={D}(D)_{F'}^+ = \{D\}
    • Attribute AA cannot be reached because no dependency in Fβ€²F' has DD on the left-hand side!
  3. Therefore, D→AD \to A cannot be derived from the projected dependencies.
  4. 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.
Common Interview Traps

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 X→YX \to Y 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.


πŸ’¬

Discussion & Doubts