-- 设置数据库字符集 ALTER DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 设置表字符集 CREATE TABLE users ( id INTPRIMARY KEY, name VARCHAR(100) ) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
📊 索引优化策略
1. 索引基础原理
B+树索引结构
1 2 3 4
MySQL InnoDB B+树索引结构: 叶子节点存储完整数据记录 非叶子节点存储索引键值 + 指针 支持范围查询和排序操作
索引的代价
维护成本: 插入、更新、删除时需要更新索引
存储成本: 索引占用额外存储空间
查询成本: 索引选择不当会降低查询性能
2. 索引设计原则
最左前缀原则
1 2 3 4 5 6 7 8 9 10 11
-- 复合索引 (name, age, city) CREATE INDEX idx_user_name_age_city ON users (name, age, city);
-- 有效查询 SELECT*FROM users WHERE name ='张三'; SELECT*FROM users WHERE name ='张三'AND age =25; SELECT*FROM users WHERE name ='张三'AND age =25AND city ='北京';
-- 无效查询(不满足最左前缀) SELECT*FROM users WHERE age =25; SELECT*FROM users WHERE city ='北京';
覆盖索引优化
1 2 3 4 5 6 7
-- 查询只需要索引中的字段 EXPLAIN SELECT name, age FROM users WHERE name ='张三';
-- 创建覆盖索引 CREATE INDEX idx_name_age ON users (name, age);
-- 查看慢查询 SHOW PROCESSLIST; SHOW ENGINE INNODB STATUS;
EXPLAIN分析执行计划
1 2 3 4 5 6 7 8 9 10
-- 分析查询执行计划 EXPLAIN SELECT*FROM orders o JOIN users u ON o.user_id = u.id WHERE o.amount >1000AND u.city ='北京';
-- 关键指标: -- type: 连接类型 (ALL < index < range < ref < eq_ref < const) -- key: 实际使用的索引 -- rows: 预估扫描行数 -- Extra: 额外信息 (Using filesort, Using temporary)
索引优化案例
1 2 3 4 5 6 7 8 9 10 11 12 13
-- 案例1:优化用户订单查询 -- 原始查询 SELECT*FROM orders WHERE user_id = ? AND created_at BETWEEN ? AND ?;
-- 创建复合索引 CREATE INDEX idx_user_date ON orders (user_id, created_at);
-- 案例2:优化商品搜索 -- 原始查询 SELECT*FROM products WHERE category = ? AND price BETWEEN ? AND ? ORDERBY sales DESC;
-- 创建复合索引 CREATE INDEX idx_cat_price_sales ON products (category, price, sales);
🚀 查询优化技术
1. SQL语句优化
子查询优化
1 2 3 4 5 6 7 8 9 10 11 12
-- 低效:相关子查询 SELECT*FROM orders o WHERE o.amount > (SELECTAVG(amount) FROM orders WHERE user_id = o.user_id);
-- 优化:使用JOIN SELECT o.*FROM orders o JOIN ( SELECT user_id, AVG(amount) as avg_amount FROM orders GROUPBY user_id ) ua ON o.user_id = ua.user_id WHERE o.amount > ua.avg_amount;
分页查询优化
1 2 3 4 5 6 7 8
-- 低效:深度分页 SELECT*FROM orders ORDERBY id LIMIT 100000, 20;
-- 优化:使用索引分页 SELECT*FROM orders WHERE id >100000ORDERBY id LIMIT 20;
-- 优化:游标分页 SELECT*FROM orders WHERE id > ? ORDERBY id LIMIT 20;
UNION优化
1 2 3 4 5 6 7
-- 低效:UNION ALL SELECT id, name FROM users WHERE status =1 UNION SELECT id, name FROM users WHERE status =2;
-- 优化:使用OR条件 SELECT id, name FROM users WHERE status IN (1, 2);
2. 连接查询优化
连接顺序优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14
-- 分析连接顺序 EXPLAIN SELECT u.name, COUNT(o.id) as order_count FROM users u LEFTJOIN orders o ON u.id = o.user_id GROUPBY u.id;
-- 优化:小表驱动大表 SELECT u.name, o.order_count FROM ( SELECT user_id, COUNT(*) as order_count FROM orders GROUPBY user_id ) o RIGHTJOIN users u ON u.id = o.user_id;
连接算法选择
1 2 3 4 5 6 7 8 9
-- Nested Loop Join (适用于小数据集) EXPLAIN SELECT*FROM users u JOIN orders o ON u.id = o.user_id;
-- Hash Join (适用于大数据集) -- MySQL 8.0.18+ 支持 Hash Join SET optimizer_switch ='hash_join=on';
-- Sort Merge Join (适用于有序数据) -- 通过索引自动选择
🔒 事务和锁优化
1. 事务隔离级别
四种隔离级别对比
隔离级别
脏读
不可重复读
幻读
性能
READ UNCOMMITTED
✅
✅
✅
最快
READ COMMITTED
❌
✅
✅
较快
REPEATABLE READ
❌
❌
✅
一般
SERIALIZABLE
❌
❌
❌
最慢
1 2 3 4 5 6
-- 查看当前隔离级别 SELECT @@transaction_isolation;
-- 设置隔离级别 SET SESSION transaction_isolation ='READ-COMMITTED'; SETGLOBAL transaction_isolation ='READ-COMMITTED';
-- 原始查询,执行时间30秒 SELECT o.id, o.amount, u.name, p.title FROM orders o JOIN users u ON o.user_id = u.id JOIN products p ON o.product_id = p.id WHERE o.created_at BETWEEN'2023-01-01'AND'2023-12-31' ORDERBY o.created_at DESC;
优化过程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
-- 1. 添加复合索引 CREATE INDEX idx_order_user_date ON orders (user_id, created_at); CREATE INDEX idx_order_product ON orders (product_id);
-- 2. 优化查询结构 SELECT o.id, o.amount, u.name, p.title FROM ( SELECT id, user_id, product_id, amount FROM orders WHERE created_at BETWEEN'2023-01-01'AND'2023-12-31' ORDERBY created_at DESC LIMIT 1000 ) o JOIN users u ON o.user_id = u.id JOIN products p ON o.product_id = p.id;
优化效果
执行时间: 从30秒降低到0.5秒
扫描行数: 从100万行降低到1000行
性能提升: 6000%
案例2:用户登录性能优化
问题描述
1 2 3
-- 用户登录查询,存在性能问题 SELECT*FROM users WHERE email = ? AND password = ? AND status ='active';
优化方案
1 2 3 4 5 6 7 8 9 10
-- 1. 添加唯一索引 CREATEUNIQUE INDEX idx_user_email ON users (email);
-- 2. 分离认证逻辑 -- 先验证用户存在性和状态 SELECT id, status FROM users WHERE email = ?;
-- 再进行密码验证 (应用层) if user_exists and user_active: verify_password(password, stored_hash)
graph TD A[收到性能告警] --> B[检查系统资源] B --> C{CPU使用率} C -->|高| D[分析慢查询] C -->|正常| E[检查内存使用] D --> F[优化索引] E --> G[调整缓冲池] F --> H[验证优化效果] G --> H H --> I[监控持续观察]