-- 原慢查询:订单列表查询 SELECT o.id, o.order_no, o.user_id, o.total_amount, o.status, o.create_time, oi.product_id, oi.product_name, oi.quantity, oi.unit_price FROM orders o LEFTJOIN order_items oi ON o.id = oi.order_id WHERE o.user_id =12345 AND o.create_time >='2024-01-01' AND o.create_time <'2024-02-01' AND o.status IN (1, 2, 3) ORDERBY o.create_time DESC LIMIT 20OFFSET0;
EXPLAIN 分析
1
EXPLAIN SELECT ...;
结果分析:
type: ALL(全表扫描)
rows: 1,200,000(扫描行数过多)
Extra: Using where; Using temporary; Using filesort
key: NULL(未使用索引)
优化方案
1. 索引优化
联合索引设计
1 2 3 4 5 6 7 8 9
-- 分析查询条件,创建最优联合索引 -- 最左前缀原则:user_id + create_time + status
ALTER TABLE orders ADD INDEX idx_user_time_status (user_id, create_time, status);
-- 覆盖索引优化 ALTER TABLE orders ADD INDEX idx_user_time_status_covering (user_id, create_time, status, order_no, total_amount);
索引选择原则
1 2 3 4 5 6 7 8
-- 查看索引使用情况 SHOW INDEX FROM orders;
-- 分析索引选择性 SELECT COUNT(DISTINCT user_id) /COUNT(*) as user_selectivity, COUNT(DISTINCT status) /COUNT(*) as status_selectivity FROM orders;
2. SQL 重写优化
优化后的查询
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
-- 优化方案1:延迟关联 SELECT o.id, o.order_no, o.user_id, o.total_amount, o.status, o.create_time FROM orders o WHERE o.user_id =12345 AND o.create_time >='2024-01-01' AND o.create_time <'2024-02-01' AND o.status IN (1, 2, 3) ORDERBY o.create_time DESC LIMIT 20;
-- 再查询订单详情 SELECT*FROM order_items WHERE order_id IN (?, ?, ?, ...);
-- 查看未使用索引的查询 SELECT TABLE_SCHEMA, TABLE_NAME, INDEX_NAME, CARDINALITY FROM information_schema.STATISTICS WHERE TABLE_SCHEMA ='your_db' AND INDEX_NAME NOTIN ( SELECT INDEX_NAME FROM performance_schema.table_io_waits_summary_by_index_usage WHERE COUNT_STAR >0 );