Exercise 2: Why JSONB Beats a Sparse Table or an EAV Pattern for Product Attributes — Possible Solution ==================================================================== THE PROBLEM ------------------------------ Per this chapter, "a shirt has size/color and a laptop has ram/ storage — wildly different fields per category, impossible to model cleanly with fixed relational columns without either a huge, mostly- empty sparse table or an entity-attribute-value (EAV) design, both worse options in their own way." WHY A SPARSE TABLE IS A WORSE OPTION ------------------------------ A single products table with one column per possible attribute across every category (size, color, ram_gb, storage_gb, and every other category's own fields) would need a column for every attribute ANY product category might ever have. Most rows would leave most of those columns NULL — a shirt row has no meaningful value for ram_gb, a laptop row has no meaningful value for color. As more product categories are added, the table keeps growing wider and sparser, becoming harder to read, harder to maintain, and wasteful of storage for all the unused columns on every row. WHY AN EAV PATTERN IS ALSO A WORSE OPTION ------------------------------ An EAV design instead stores each attribute as its own row (product_id, attribute_name, attribute_value) in a separate table. This avoids the sparse-columns problem, but trades it for a different one: every attribute lookup now requires a join or multiple rows per product, querying becomes awkward (comparing numeric values stored as generic text becomes error-prone), and there's no natural place to enforce that a "laptop" product actually has the right SET of attributes versus a "shirt" product. WHY JSONB IS A BETTER FIT THAN EITHER ------------------------------ Per this chapter's own example, a single JSONB attributes column lets each product store exactly the fields relevant to its own category — '{"size": "M", "color": "blue"}' for a shirt, '{"ram_gb": 32, "storage_gb": 1024}' for a laptop — with no wasted NULL columns and no row-per-attribute join overhead. Per this chapter's own query example, attributes can still be queried directly and efficiently: SELECT name FROM products WHERE category = 'laptop' AND (attributes ->> 'ram_gb')::int >= 16; And per this chapter's own Indexing section, a GIN index on the attributes column keeps this fast even at real scale — something neither the sparse-table nor the EAV approach handles as cleanly. WHY THIS WORKS AS AN ANSWER ------------------------------ It explains the concrete downside of both named alternatives, then shows specifically how JSONB avoids both downsides using the chapter's own schema and query example, rather than just asserting JSONB is more convenient.