70 phút
Indexes và Query Optimization
Giới thiệu Indexes
Indexes giúp cải thiện performance của queries bằng cách cung cấp cấu trúc dữ liệu để tìm kiếm nhanh.
Types of Indexes
B-Tree Index (Mặc định)
-- Single column index
CREATE INDEX idx_customer_email ON customers(email);
-- Composite index
CREATE INDEX idx_orders_date_customer ON orders(order_date, customer_id);
-- Unique index
CREATE UNIQUE INDEX idx_unique_product_sku ON products(sku);
Partial Index
-- Chỉ index các bản ghi active
CREATE INDEX idx_active_products ON products(name)
WHERE is_active = true;
Expression Index
-- Index trên kết quả của expression
CREATE INDEX idx_lower_product_name ON products(LOWER(name));
Query Execution Plans
EXPLAIN Command
EXPLAIN SELECT * FROM orders WHERE customer_id = 123;
EXPLAIN ANALYZE
EXPLAIN ANALYZE
SELECT * FROM orders
WHERE order_date BETWEEN '2024-01-01' AND '2024-12-31';
Query Optimization Techniques
Sargable Queries
-- KHÔNG Sargable (không sử dụng index)
SELECT * FROM products WHERE YEAR(created_date) = 2024;
-- Sargable (sử dụng index)
SELECT * FROM products
WHERE created_date BETWEEN '2024-01-01' AND '2024-12-31';
Avoid SELECT *
-- KHÔNG TỐT
SELECT * FROM customers WHERE city = 'Hanoi';
-- TỐT HƠN
SELECT customer_id, name, email
FROM customers
WHERE city = 'Hanoi';
JOIN Optimization
-- Sử dụng EXISTS thay vì IN cho subqueries lớn
SELECT c.*
FROM customers c
WHERE EXISTS (
SELECT 1 FROM orders o
WHERE o.customer_id = c.customer_id
AND o.total_amount > 1000
);
Index Strategy
Khi nào nên tạo Index
- Columns trong WHERE clause
- Columns trong JOIN conditions
- Columns trong ORDER BY
- Foreign keys
Khi nào KHÔNG nên tạo Index
- Tables nhỏ
- Columns thường xuyên được update
- Columns có cardinality thấp (ít giá trị unique)
Monitoring Index Usage
-- PostgreSQL: xem index usage
SELECT * FROM pg_stat_user_indexes;
-- MySQL: xem index usage
SHOW INDEX FROM table_name;
Common Performance Issues
N+1 Query Problem
-- VẤN ĐỀ: Một query lấy danh sách + N queries lấy chi tiết
SELECT * FROM orders WHERE customer_id = 123; -- 1 query
-- Sau đó với mỗi order:
SELECT * FROM order_items WHERE order_id = ?; -- N queries
-- GIẢI PHÁP: Sử dụng JOIN hoặc batch query
SELECT o.*, oi.*
FROM orders o
LEFT JOIN order_items oi ON o.order_id = oi.order_id
WHERE o.customer_id = 123;
Missing Indexes
-- Query chậm do thiếu index
SELECT * FROM orders
WHERE status = 'shipped'
AND order_date >= '2024-01-01';
-- Tạo composite index
CREATE INDEX idx_orders_status_date
ON orders(status, order_date);