Databases
Relational model: multiple-choice review
Six questions that cut across the whole unit. None is a definition to recite — each is a schema-design decision you make under real constraints, where the wrong call is paid back at migration time, not design time.
Confirm you can connect the unit’s spine: keys and constraints, normal forms vs deliberate denormalization, JSONB vs typed columns vs side tables, FK economics at scale, physical storage, and how a schema changes without downtime.
A customer table uses email as its PRIMARY KEY. Marketing now wants users to be able to change their email. What is the core problem, and the standard fix?
A table stores `orders(order_id, customer_id, customer_city)` where `order_id` alone is the primary key. Which normal form does it violate, and what breaks in production?
A marketplace needs free-form product tags supporting four queries: show a product's tags, list all products with tag X, count products per tag, and rename a tag globally. Which storage shape satisfies all four cheaply at scale?
A senior engineer proposes disabling foreign keys across a typical B2B SaaS schema (tables under 100M rows) to 'improve write performance'. How should you read this proposal?
`SELECT * FROM events ORDER BY created_at DESC LIMIT 100` on a 50M-row table with an index on created_at is 3× slower than expected. The table has an 8KB-average JSONB payload column. Most likely cause and fix?
A `user_name` column must become `display_name` on a 50M-row table shared by many services, with zero downtime. Which approach is correct, and why is the one-line rename wrong?
The through-line across the unit is one decision discipline: put identity in an immutable surrogate key and guard business keys with UNIQUE NOT NULL; normalize to 3NF so no two rows can disagree, and denormalize only with explicit reconciliation; reach for a side table the moment you query from the other direction; keep FK constraints unless a measured sharding or cascade constraint forces otherwise; remember that physical storage (TOAST, page layout) makes SELECT * expensive on wide rows; and change a live schema with expand-then-contract, never an in-place break. Every answer here resolves back to “design for the queries and the lifetime, not the first insert.”