Database ManagementUnit 611 min read
Query Processing & Optimization: Execution Plans, Indexes, Joins, Cost Models
Unit 6 of Database Management: explores how databases execute SQL queries efficiently, from parsing and optimization to execution plans, indexing strategies, join algorithms, and cost-based optimization techniques.
TAKEAWAYS:
- Query execution follows a three-phase process: parsing → optimization → execution, with each phase transforming the query into an efficient plan.
- Indexing (B-trees, hash, bitmap) speeds up searches but adds storage and write overhead; choose based on query patterns.
- Join algorithms (nested loops, hash join, merge join) differ in cost and suitability for sorted/unsorted data.
- Cost-based optimization uses statistical metadata (e.g., table sizes, selectivity) to pick the cheapest execution plan.
- Query rewriting (e.g., predicate pushdown, view merging) can drastically reduce I/O and computation.
- Real-world systems like NEPSE (stock market) and Daraz (e-commerce) rely on optimized queries to handle millions of transactions per second.
1. Query Processing Overview
Databases don’t run SQL queries directly—they process them in stages to generate an efficient execution plan. Think of it like a chef preparing a dish:
- Parsing: Checks syntax and converts SQL into an abstract syntax tree (AST).
- Optimization: Rewrites the query (e.g., simplifies joins, pushes filters down) and selects the best plan.
- Execution: Runs the plan step-by-step, accessing data via indexes or full scans.
Why it matters: Without optimization, even simple queries (e.g., "Find all Daraz orders shipped to Kathmandu in 2023") could scan millions of rows inefficiently.
2. The Optimization Phase: How Databases Choose the Best Plan
The optimizer compares multiple execution plans (e.g., two joins in different orders) and picks the cheapest one based on:
- Statistics: Table sizes, column distributions (e.g., 80% of NEPSE trades are under ₹500).
- Cost models: Estimates I/O, CPU, and memory usage (e.g., a hash join might be faster for unsorted data).
Key Techniques
| Technique | Description | Example Use Case |
|---|---|---|
| Predicate Pushdown | Moves WHERE filters to earlier stages to reduce rows early. |
SELECT * FROM orders WHERE status='shipped' → filter before joining with customers. |
| Join Reordering | Changes join order to minimize intermediate result sizes. | A JOIN B JOIN C → B JOIN C first if B is smallest. |
| View Merging | Replaces views with their base tables to avoid extra scans. | SELECT * FROM view_high_value_customers → merge with customers directly. |
| Subquery Rewriting | Converts correlated subqueries to joins for efficiency. | WHERE order_id IN (SELECT id FROM high_value_orders) → JOIN high_value_orders. |
Visual: Cost comparison of two plans for SELECT * FROM orders JOIN customers ON orders.customer_id = customers.id:
Worked Example: NEPSE’s Trade Query Suppose NEPSE runs:
SELECT t.symbol, SUM(t.quantity)
FROM trades t
WHERE t.timestamp > '2023-01-01'
GROUP BY t.symbol;
- Bad plan: Scans all trades (millions of rows) → groups → filters.
- Optimized plan:
- Predicate pushdown: Filters
timestampearly (reduces rows by 90%). - Index scan: Uses a B-tree on
timestamp(if indexed). - Hash aggregation: Groups remaining rows in memory.
- Predicate pushdown: Filters
3. Indexes: The Secret Weapon for Fast Queries
Indexes are data structures (B-trees, hash, bitmap) that speed up searches but slow down writes. Choose wisely!
Index Types
| Index Type | Best For | Drawback | Example in Nepal |
|---|---|---|---|
| B-tree | Range queries (>, <, BETWEEN) |
Higher memory usage | NEPSE’s symbol index for stock lookups. |
| Hash | Exact-match equality (=) |
No range support | Khalti’s user_id → account lookup. |
| Bitmap | Low-cardinality columns (e.g., gender) |
High overhead for large tables | Daraz’s category index (e.g., "electronics"). |
How indexes work:
- B-tree: Balanced tree where leaves hold sorted keys (like a phone book).
- Hash: Direct mapping (e.g.,
user_id→password_hash). - Bitmap: Bit arrays for categorical data (e.g.,
status= "active" or "inactive").
Worked Example: Pathao’s Ride Search
Pathao’s app uses a composite index on (pickup_location, dropoff_location, timestamp) to:
- Quickly find rides near you (B-tree on
pickup_location). - Filter by time (range scan on
timestamp). - Avoid full table scans during peak hours (e.g., 6–9 PM).
When NOT to index:
- Tables with frequent updates (indexes slow
INSERT/UPDATE). - Columns used in sorts/joins (unless selective).
4. Join Algorithms: How Databases Combine Tables
Joins are expensive—databases use different strategies based on data size and sort status.
| Algorithm | When to Use | Cost Example (1M rows) | Nepal Use Case |
|---|---|---|---|
| Nested Loop | Small table joined to large table | O(n²) if no index | Ncell’s customer → bill join (small customer table). |
| Hash Join | Unsorted data, medium tables | O(n + m) | Daraz’s orders → products join (hashes order_id). |
| Merge Join | Sorted data (e.g., by customer_id) |
O(n log n) | NEPSE’s trades → stocks join (sorted by symbol). |
Visual: Hash join steps for orders JOIN products:
Worked Example: Bank Loan Approval A bank runs:
SELECT c.name, SUM(l.amount)
FROM customers c
JOIN loans l ON c.id = l.customer_id
WHERE l.status = 'approved';
- Optimized plan:
- Hash join: Builds a hash table on
customer_id(fromloans). - Probe: Joins with
customers(faster than nested loops ifloansis large).
- Hash join: Builds a hash table on
5. Cost-Based Optimization: The Math Behind "Cheapest Plan"
Databases use statistics (e.g., table sizes, column distributions) to estimate costs. For example:
| Metric | Formula | Example (Ncell Bills) |
|---|---|---|
| Table size | rows × avg_row_size |
bills table: 5M rows × 1KB = 5GB. |
| Selectivity | distinct_values / total_rows |
status column: 3 distinct values → selectivity = 0.003. |
| Join cost | size(A) × size(B) (nested loop) |
customers (10K) × orders (1M) = 10B ops. |
Worked Example: Khalti’s Transaction Query Khalti optimizes:
SELECT u.name, COUNT(t.id)
FROM users u
JOIN transactions t ON u.id = t.user_id
WHERE t.amount > 1000;
- Cost model:
transactionshas 10M rows, 80% are >₹1000 → selectivity = 0.8.- Nested loop cost:
users(1M) ×transactions(10M) × 0.8 = 8B ops. - Hash join cost:
users(1M) +transactions(10M) × 0.8 = 9M ops → cheaper.
6. Query Rewriting: Tricks to Save Resources
Databases rewrite queries to avoid redundant work. Examples:
- Predicate pushdown: Move
WHEREclauses to earlier stages.-- Before: Scan all orders, then filter. SELECT * FROM orders WHERE status = 'shipped'; -- After: Filter first (if index exists). SELECT * FROM orders WHERE status = 'shipped'; - View merging: Replace views with their base tables.
-- Before: Scan `high_value_customers` (view) → scan `orders` again. SELECT * FROM high_value_customers; -- After: Direct join with `orders`. SELECT * FROM customers c JOIN orders o ON c.id = o.customer_id WHERE o.amount > 10000; - Common table expressions (CTEs): Break complex queries into steps.
WITH top_customers AS ( SELECT customer_id, SUM(amount) as total FROM orders GROUP BY customer_id ORDER BY total DESC LIMIT 100 ) SELECT * FROM top_customers;
In the Real World
NEPSE (Nepal Stock Exchange)
- Idea: Indexed range scans on
timestampandsymbolcolumns. - How: Trades are stored in a B-tree indexed by
timestampto quickly fetch daily summaries (e.g., "Top 10 stocks by volume on 2023-10-01"). - Worked example: A query like
SELECT * FROM trades WHERE timestamp BETWEEN '2023-10-01' AND '2023-10-31'uses a range scan on the index instead of scanning all 50M trades.
- Idea: Indexed range scans on
Daraz (E-commerce)
- Idea: Hash joins for product-customer relationships.
- How: When a user searches for "laptops," Daraz joins
products(1M rows) withcustomer_reviews(5M rows) using a hash table onproduct_id. Without optimization, this would take hours. - Real query:
SELECT p.name, AVG(r.rating) FROM products p JOIN reviews r ON p.id = r.product_id WHERE p.category = 'electronics' GROUP BY p.id;
Ncell (Telecom)
- Idea: Predicate pushdown in bill generation.
- How: When generating monthly bills, Ncell filters inactive users early (using a bitmap index on
status) before joining with call logs (100M rows). This reduces the join size by 95%.
Exam Tip
Focus on trade-offs:
- Indexes speed up reads but slow down writes. Example: "Why doesn’t NEPSE index
trades.timestampfor all queries?" → "Because frequent updates (new trades) would degrade performance." - Joins: Nested loops are simple but slow for large tables. Example: "How would you optimize
SELECT * FROM orders JOIN customersifordersis 100x larger thancustomers?" → "Use a hash join withcustomersas the build table."
- Indexes speed up reads but slow down writes. Example: "Why doesn’t NEPSE index
Draw execution plans:
- Always sketch the before/after optimization for a query. Example:
Before: Full scan (orders) → Full scan (customers) → Join After: Index scan (orders.customer_id) → Hash join
- Always sketch the before/after optimization for a query. Example:
Cost-based questions:
- Given table sizes and selectivity, calculate which join is cheaper. Example:
- Table A: 10K rows, Table B: 1M rows, join on
id. - Nested loop cost: 10K × 1M = 10B ops.
- Hash join cost: 1M (build) + 10K (probe) = 1.01M ops → hash join wins.
- Table A: 10K rows, Table B: 1M rows, join on
- Given table sizes and selectivity, calculate which join is cheaper. Example:
Real-world mapping:
- Link concepts to Nepalese apps. Example:
- "How does Pathao use indexes?" → "Composite index on
(pickup_location, dropoff_location, timestamp)for fast ride searches." - "Why does Khalti use hash joins?" → "Transactions are unsorted, but hash joins are efficient for exact-match lookups."
- "How does Pathao use indexes?" → "Composite index on
- Link concepts to Nepalese apps. Example:
Common pitfalls:
- Ignoring statistics: Always assume the optimizer has up-to-date stats (e.g., table sizes, column distributions).
- Over-indexing: Don’t index every column—focus on selective columns (e.g.,
emailis better thanlast_namefor lookups). - Forgetting join order:
A JOIN B JOIN Cis not always the same asB JOIN C JOIN A—cost depends on table sizes.
Final Visual: Query optimization pipeline (recap)
Based on the TU BBM syllabus for Database Management (COM312), unit 6.
Discussion
Loading…