Bird
Raised Fist0
Interview Prepdatabase-management-systemshardGoogleAmazonFlipkartCRED

Lossless Join & Dependency Preservation in Decomposition

Choose your preparation mode3 modes available
▶
Steps
setup

Initialize Relation and Functional Dependencies

The algorithm starts by representing the original relation R with attributes A, B, C, D as the root node in the tree. Functional dependencies are noted but not yet applied.

💡 Initialization sets the base schema from which decomposition will proceed, making clear what attributes and dependencies are involved.
Line:R = Relation(['A','B','C','D']) # STEP 1
💡 The root node contains all attributes, showing the starting point before decomposition.
📊
Lossless Join & Dependency Preservation in Decomposition - Watch the Algorithm Execute, Step by Step
Watching this step-by-step visualization helps you understand the subtle conditions that guarantee lossless join and dependency preservation, which are often abstract in theory.
Step 1/11
·Active fill★Answer cell
setup
ABCD
leaf
Initialize root node with all attributes of relation R.
traverseKey: A -> B
ABCD
leaf
Select functional dependency A -> B for processing.
compareKey: A -> B
ABCD
leaf
Check if schema contains both A and B to decide on decomposition.
splitKey: A -> B↑ promoted: A
ABCD
AB
leaf
CD
leaf
Split root node into R1(A,B) and R2(C,D) to preserve A -> B.
traverseKey: B -> C
ABCD
AB
leaf
CD
leaf
Focus on node with B to check dependency B -> C.
compareKey: B -> C
ABCD
AB
leaf
CD
leaf
Check if B and C are in the same node to preserve B -> C.
splitKey: B -> C↑ promoted: C
ABCD
AB
leaf
CD
C
leaf
D
leaf
Split node {C,D} into {C} and {D} to preserve B -> C.
traverseKey: C -> D
ABCD
AB
leaf
CD
C
leaf
D
leaf
Focus on node with C to check dependency C -> D.
compareKey: C -> D
ABCD
AB
leaf
CD
C
leaf
D
leaf
Check if C and D are in the same or connected nodes to preserve C -> D.
compare
ABCD
AB
leaf
CD
C
leaf
D
leaf
Verify intersections of decomposed schemas ensure lossless join.
reconstruct
ABCD
AB
leaf
BC
C
leaf
D
leaf
Output final decomposition preserving lossless join and dependencies.

Key Takeaways

✓ Decomposition must isolate dependencies to preserve them while ensuring lossless join.

This is hard to see from code alone because the interplay between dependencies and schema splits is subtle.

✓ Lossless join depends on intersections of decomposed schemas containing keys that enable correct joins.

Visualizing the tree clarifies how intersections guarantee no data loss.

✓ Sequentially processing each functional dependency guides the decomposition steps and decisions.

The trace shows how each dependency influences the tree structure and decomposition.

Practice

(1/5)
1. Trace the sequence of events when two transactions concurrently update the same row under pessimistic locking with row-level locks. What happens if the second transaction tries to acquire the lock while the first holds it?
easy
A. The second transaction immediately aborts with a deadlock error
B. The second transaction acquires a shared lock and reads the row but cannot update
C. The second transaction proceeds and overwrites the first transaction's changes
D. The second transaction waits until the first transaction commits or rolls back

Solution

  1. Step 1: Understand pessimistic locking behavior

    Pessimistic locking blocks conflicting operations to prevent concurrency issues.
  2. Step 2: Analyze lock acquisition

    When the first transaction holds an exclusive row-level lock, the second transaction must wait to acquire the same exclusive lock.
  3. Step 3: Outcome of concurrent update attempts

    The second transaction is blocked until the first commits or rolls back, releasing the lock.
  4. Final Answer:

    Option D -> Option D
  5. Quick Check:

    Waiting prevents dirty writes and ensures serializability under pessimistic concurrency control.
Hint: Pessimistic locks cause waiting, not immediate aborts or overwrites.
Common Mistakes:
  • Thinking the second transaction aborts immediately
  • Assuming the second transaction can overwrite without waiting
  • Confusing shared and exclusive locks in updates
2. Consider a 1:N relationship between entities Department and Employee, where one department has many employees. When a new employee is added, what is the sequence of steps to maintain referential integrity in the database?
easy
A. Insert the employee record without any reference to the department.
B. Insert the employee record with a foreign key referencing the department's primary key; verify the department exists.
C. Insert the department record with a foreign key referencing the employee's primary key.
D. Insert the employee record first, then create the department record if missing.

Solution

  1. Step 1: Understand the 1:N relationship

    Each employee belongs to one department; department is the 'one' side.
  2. Step 2: Referential integrity requires foreign key

    Employee table must have a foreign key referencing Department's primary key.
  3. Step 3: Insert employee with valid department reference

    Before inserting employee, ensure the department exists to avoid foreign key violation.
  4. Step 4: Evaluate other options

    Insert the employee record first, then create the department record if missing inserts employee before department, risking integrity violation. Insert the department record with a foreign key referencing the employee's primary key reverses foreign key direction, which is incorrect. Insert the employee record without any reference to the department omits foreign key, breaking relationship.
  5. Final Answer:

    Option B -> Option B
  6. Quick Check:

    Foreign keys must reference existing primary keys to maintain integrity.
Hint: In 1:N, the 'many' side holds the foreign key referencing the 'one' side.
Common Mistakes:
  • Inserting dependent records before referenced records
  • Misplacing foreign keys on the 'one' side instead of 'many' side
3. Given the following SQL query executed on the Employee table with rows (1,100), (2,200), (3,300), (4,300), what is the output printed by the Python code below?
import sqlite3

conn = sqlite3.connect(':memory:')
cursor = conn.cursor()
cursor.execute('CREATE TABLE Employee(Id INTEGER, Salary INTEGER)')
cursor.executemany('INSERT INTO Employee VALUES (?, ?)', [(1, 100), (2, 200), (3, 300), (4, 300)])

query = '''
SELECT Salary FROM (
  SELECT DISTINCT Salary FROM Employee
  ORDER BY Salary DESC
  LIMIT 1 OFFSET 1
)
'''
cursor.execute(query)
result = cursor.fetchone()
print(result[0] if result else 'NULL')
conn.close()
easy
A. 300
B. NULL
C. 100
D. 200

Solution

  1. Step 1: Identify distinct salaries and order descending

    Distinct salaries are [300, 200, 100] ordered descending.
  2. Step 2: Apply LIMIT 1 OFFSET 1

    OFFSET 1 skips the highest (300), LIMIT 1 picks the next, which is 200.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Distinct ordering and offset correctly select second highest salary [OK]
Hint: OFFSET 1 skips highest, LIMIT 1 picks second highest [OK]
Common Mistakes:
  • Confusing OFFSET 1 to pick highest
  • Not using DISTINCT leads to duplicate highest salary
4. Given the following Python code simulating a JOIN to find customers with orders, what is the output of the print statement?
easy
A. ['Alice', 'Bob', 'Charlie']
B. ['Bob', 'Charlie']
C. ['Alice']
D. ['Alice', 'Bob']

Solution

  1. Step 1: Trace order_customer_ids set

    Extract customer IDs from orders: {1, 2}.
  2. Step 2: Filter customers by IDs in order_customer_ids

    Customers with id 1 and 2 are Alice and Bob; Charlie (id 3) is excluded.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Only Alice and Bob have orders, matching output [OK]
Hint: Set membership filters customers with orders correctly [OK]
Common Mistakes:
  • Including customers without orders
  • Off-by-one errors in filtering
  • Confusing customer IDs with order IDs
5. In a geo-distributed NoSQL system designed for high availability and partition tolerance, an application requires strict consistency for a subset of critical transactions. Which approach best addresses this requirement without sacrificing overall system availability?
hard
A. Switch the entire system to a strongly consistent SQL database cluster
B. Accept eventual consistency for all transactions to maintain availability
C. Implement a hybrid approach using multi-model databases or selective consistency zones for critical data
D. Use synchronous replication across all nodes for all data to guarantee consistency

Solution

  1. Step 1: Understand system constraints

    The system is geo-distributed, prioritizing availability and partition tolerance, but needs strict consistency for some transactions.
  2. Step 2: Evaluate options

    Switch the entire system to a strongly consistent SQL database cluster sacrifices availability globally, which is undesirable. Accept eventual consistency for all transactions to maintain availability ignores strict consistency needs. Use synchronous replication across all nodes for all data to guarantee consistency sacrifices availability due to synchronous replication delays.
  3. Step 3: Hybrid solution

    Implement a hybrid approach using multi-model databases or selective consistency zones for critical data proposes selective consistency zones or multi-model databases, allowing critical transactions to be strongly consistent while maintaining availability elsewhere.
  4. Final Answer:

    Option C -> Option C
  5. Quick Check:

    Hybrid approaches balance consistency and availability per data criticality [OK]
Hint: Hybrid selective consistency zones enable strict consistency without losing availability globally
Common Mistakes:
  • Thinking entire system must switch to SQL for consistency
  • Assuming eventual consistency suffices for critical transactions
  • Believing synchronous replication is always feasible in geo-distributed setups
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard