Katkat

Design E-Commerce Tables and Indexes for Recent-Spend Queries

VisaSoftware Engineer I · Online Assessment

Last updated

This question tests database schema normalization, data integrity in e-commerce transactions, and the ability to optimize SQL queries using indexing strategies.

Schema Design and Optimization

You are designing the core database schema for an e-commerce platform. The system must track users, products, orders, and order line items. A critical requirement is that when a user places an order, the price of each item must be snapshotted at that moment, as product prices change over time.

1. Schema Design

Define a normalized relational schema with the following tables:

  • Users: user_id (PK), email, created_at.
  • Products: product_id (PK), current_price, stock_quantity.
  • Orders: order_id (PK), user_id (FK), status (e.g., 'pending', 'completed'), created_at.
  • Order_Items: item_id (PK), order_id (FK), product_id (FK), captured_price.

Explain how you ensure data consistency for captured_price and what integrity constraints you would apply to the Order_Items table.

2. Query and Indexing

Write a SQL query to calculate the total spend of each user for all completed orders placed in the last 30 days.

-- Example Target Query
SELECT user_id, SUM(captured_price) as total_spent
FROM Orders O
JOIN Order_Items OI ON O.order_id = OI.order_id
WHERE O.status = 'completed' AND O.created_at >= NOW() - INTERVAL '30 days'
GROUP BY user_id;

Propose a set of indexes to optimize this query. Provide the specific CREATE INDEX statements and explain why your chosen columns and order (column cardinality/prefixing) benefit the execution plan.

3. Evaluation

Briefly explain what you would look for in a EXPLAIN ANALYZE output to verify that your indexes are effectively reducing scan costs.

Hints

Hint 1

Consider why you must store a price in the Order_Items table rather than simply referencing the current price in the Products table.

Hint 2

For the index, consider a composite index that covers the filtering conditions in the WHERE clause first, followed by join keys.

Hint 3

Think about how an Index Range Scan on a date column might interact with the status filter and join operations.

Follow-up questions

  • How would you handle the database migration if you needed to add a 'discount_code' field to the Order_Items table after the system has been live for a year?
  • What are the trade-offs of using a composite index on (status, created_at) versus separate indexes for each column?
  • If the number of orders per user is extremely high, how might you optimize this calculation further (e.g., materialized views or asynchronous pre-aggregation)?