Database Design
Mini Project
Build a complete database system for BookVault from scratch, applying all design principles learned throughout this module.
Project Overview: BookVault Database System
Your mission: design and implement the complete database for BookVault, our online bookstore. This project combines every concept from the previous 34 lessons. You'll identify entities, create ER diagrams, normalize tables, implement physical design, optimize for performance, and consider scalability.
Think Amazon's book section, but simpler. Customers browse books, place orders, leave reviews. Authors publish books through publishers. Books belong to categories. Inventory gets managed. Sales get tracked.
Project Scope
You'll handle customer management, book catalog, order processing, inventory tracking, author management, reviews system, and basic analytics. Real-world complexity, but focused scope.
Phase 1: Requirements Analysis
Start with business requirements. What does BookVault actually need to do?
Customer Operations
Registration, login, profile management, order history, wishlist, reviews
Book Management
Catalog browsing, search, categories, author info, inventory, pricing
Order Processing
Shopping cart, checkout, payment tracking, shipping, order status
Business Analytics
Sales reports, popular books, customer behavior, inventory alerts
Key Business Rules
Every database has rules. BookVault's rules drive our design decisions.
- One customer can place multiple orders
- One order contains multiple books (different quantities)
- One book can have multiple authors (think textbooks)
- One author writes multiple books
- Books belong to one primary category, but can have subcategories
- Customers can review books they've purchased
- Inventory must be tracked and updated with each sale
Phase 2: Entity-Relationship Design
Now we identify entities and relationships. Think nouns (entities) and verbs (relationships).
first_name
last_name
password_hash
city
created_at
FK category_id
title
isbn
price
stock_qty
published_year
description
first_name
last_name
nationality
birth_year
biography
FK customer_id
order_date
status
total_amount
shipping_address
FK order_id
FK book_id
quantity
unit_price
name
FK parent_category_id
description
Relationship Analysis
The trickiest part? Many-to-many relationships need junction tables. Books and authors have a many-to-many relationship - one book can have multiple authors, one author writes multiple books.
-- Junction table for Books-Authors many-to-many relationship
-- Eliminates redundancy and maintains data integrity
CREATE TABLE book_authors (
book_id INT,
author_id INT,
author_order SMALLINT DEFAULT 1,
PRIMARY KEY (book_id, author_id),
FOREIGN KEY (book_id) REFERENCES books(book_id),
FOREIGN KEY (author_id) REFERENCES authors(author_id)
);
Phase 3: Normalization Strategy
Time for normalization. We'll apply First, Second, and Third Normal Form systematically.
| order_id | customer_name | books |
|---|---|---|
| 1001 | John Doe | Python Guide, SQL Basics |
| 1002 | Jane Smith | Python Guide |
Problems: Repeating groups, update anomalies
| order_id | customer_id | book_id |
|---|---|---|
| 1001 | 501 | 201 |
| 1001 | 501 | 202 |
Clean: Atomic values, proper relationships
Phase 4: Physical Implementation
Now we create the actual tables. This is where theory meets reality.
-- Create BookVault database schema
-- Start with customers - the foundation of our business
CREATE TABLE customers (
customer_id INT PRIMARY KEY AUTO_INCREMENT,
first_name VARCHAR(50) NOT NULL,
last_name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
city VARCHAR(50),
phone VARCHAR(20),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
Table created successfully.
-- Categories table with self-referencing hierarchy
-- Supports parent/child category structure (Fiction -> Mystery)
CREATE TABLE categories (
category_id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
parent_category_id INT,
description TEXT,
FOREIGN KEY (parent_category_id) REFERENCES categories(category_id)
);
Table created successfully.
-- Books table - the heart of our inventory system
-- Includes business-critical fields like stock and pricing
CREATE TABLE books (
book_id INT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(255) NOT NULL,
isbn VARCHAR(13) UNIQUE,
category_id INT NOT NULL,
price DECIMAL(10, 2) NOT NULL,
stock_qty INT DEFAULT 0,
published_year YEAR,
description TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (category_id) REFERENCES categories(category_id),
INDEX idx_title (title),
INDEX idx_category (category_id),
INDEX idx_stock (stock_qty)
);
Table created successfully.
What just happened?
We created indexes on title, category_id, and stock_qty because customers will search by title, browse by category, and we need to quickly check stock levels.
Phase 5: Performance Optimization
Real databases need real performance. Indexes make queries fast, but slow down inserts. We need balance.
-- Create composite index for common query patterns
-- Customers often search: "Show me books in Fiction under $20"
CREATE INDEX idx_category_price ON books(category_id, price);
-- Orders are frequently queried by customer and date
CREATE INDEX idx_customer_date ON orders(customer_id, order_date);
-- Email lookups need to be lightning fast for login
CREATE UNIQUE INDEX idx_customer_email ON customers(email);
Indexes created successfully.
Query Performance Testing
-- Test query: Find all mystery books under $25
-- This query hits our composite index perfectly
EXPLAIN SELECT b.title, b.price, c.name as category
FROM books b
JOIN categories c ON b.category_id = c.category_id
WHERE c.name = 'Mystery' AND b.price < 25.00
ORDER BY b.price;
+----+-------+--------+------+---------------+---------+ | id | type | table | key | possible_keys | ref | +----+-------+--------+------+---------------+---------+ | 1 | ref | books | idx | category_price| const | | 2 | eq_ref| cat | pri | PRIMARY | b.cat_id| +----+-------+--------+------+---------------+---------+
Data Insight
The EXPLAIN output shows our index is being used (key = idx). Without this index, MySQL would scan all 50,000 books. With it, we scan maybe 200 mystery books.
Phase 6: Advanced Features
Modern databases need modern features. Reviews, ratings, search functionality, and analytics.
-- Reviews table with rating and helpful votes
-- Supports Amazon-style review system
CREATE TABLE reviews (
review_id INT PRIMARY KEY AUTO_INCREMENT,
customer_id INT NOT NULL,
book_id INT NOT NULL,
rating TINYINT CHECK (rating BETWEEN 1 AND 5),
review_text TEXT,
helpful_votes INT DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (customer_id) REFERENCES customers(customer_id),
FOREIGN KEY (book_id) REFERENCES books(book_id),
UNIQUE KEY unique_customer_book (customer_id, book_id)
);
Table created successfully.
-- Analytics view for business intelligence
-- Calculates average ratings and review counts
CREATE VIEW book_analytics AS
SELECT
b.book_id,
b.title,
b.price,
b.stock_qty,
COALESCE(AVG(r.rating), 0) as avg_rating,
COUNT(r.review_id) as review_count,
SUM(oi.quantity) as total_sold
FROM books b
LEFT JOIN reviews r ON b.book_id = r.book_id
LEFT JOIN order_items oi ON b.book_id = oi.book_id
GROUP BY b.book_id, b.title, b.price, b.stock_qty;
View created successfully.
Testing the Complete System
-- Insert sample data to test relationships
-- Real data reveals design flaws quickly
INSERT INTO customers (first_name, last_name, email, city) VALUES
('John', 'Doe', 'john@example.com', 'New York'),
('Jane', 'Smith', 'jane@example.com', 'Chicago');
INSERT INTO categories (name, description) VALUES
('Fiction', 'Fictional literature'),
('Mystery', 'Mystery and thriller books'),
('Programming', 'Computer programming guides');
INSERT INTO authors (first_name, last_name, nationality) VALUES
('Agatha', 'Christie', 'British'),
('Robert', 'Martin', 'American');
3 rows inserted into customers. 3 rows inserted into categories. 2 rows inserted into authors.
Common Mistake
Don't forget to populate junction tables like book_authors. Many-to-many relationships break without the connecting data.
Project Validation
How do you know if your database design works? Test it with real scenarios.
Your database passes if every user story works smoothly. Can customers find books? Do orders process correctly? Are reviews tied to the right books? If any step fails, revisit your relationships.
Success Criteria: Your BookVault database handles 1000+ customers, 5000+ books, complex searches under 100ms, maintains data integrity during concurrent orders, and provides accurate business analytics.
Quiz
1. In the BookVault database, how should you handle the many-to-many relationship between books and authors?
2. Why would you create a composite index on (category_id, price) in the BookVault books table?
3. In the BookVault reviews system, how do you prevent customers from reviewing the same book multiple times?
Up Next
Course Complete!
You've mastered database design from theory to practice - time to build your own systems with confidence.