MySQL 索引的最左原则
🍰 最左原则本质
=͟͟͞͞( •̀д•́) 想象复合索引是电话号码簿!
索引 (a,b,c)
的排列顺序:
先按a排序 → a相同按b排序 → 最后按c排序
生效场景三连:
1️⃣ WHERE a=1
✅
2️⃣ WHERE a=1 AND b=2
✅
3️⃣ WHERE a=1 AND b=2 AND c=3
✅
💣 失效场景三连:
1️⃣ WHERE b=2
❌ (跳过了a)
2️⃣ WHERE a=1 AND c=3
❌ (中间断了b)
3️⃣ WHERE b=2 AND c=3
❌ (首列失踪)
✨ 特殊技巧:
WHERE a>1 AND b=2
→ 只有a能用索引(范围查询后断链)WHERE a=1 ORDER BY b,c
→ 排序也能用索引!WHERE a LIKE '张%'
✅ (前缀匹配)
哦呜(°ロ°)!曼波举个栗子:
索引是(班级, 姓名, 年龄)
✅ 查"3班 张三" → 直接翻到3班区域找张三
❌ 直接查"年龄18" → 要扫描全校学生
InnoDB 和 Mylsam 引擎的区别?
这两个引擎的区别就像奶茶和咖啡的选择,要根据场景来pick哦!
🍵 MyISAM(经典奶茶型)
=͟͟͞͞( •̀д•́) 适合读多写少的场景!
- 不支持事务(像现金交易,要么成功要么失败)
- 表级锁(修改时要锁整个表)
- 存储结构:
.MYD
数据文件 +.MYI
索引文件(像分开的奶茶和珍珠) - 特色技能:
✅ 全文索引
✅ COUNT(*) 超快(自带计数器)
❌ 崩溃后容易数据损坏
☕ InnoDB(现代咖啡机型)
(๑•̀ㅂ•́)و✧ 适合高并发事务场景!
- 支持ACID事务(像电子支付可回滚)
- 行级锁(只锁修改的行)
- 存储结构:
聚簇索引(数据&索引存在一起像浓缩咖啡) - 特色技能:
✅ 外键约束
✅ 崩溃自动恢复(redo log像咖啡机自动清洁)
✅ MVCC多版本并发控制
📊 性能对比小剧场:
- 全表COUNT:MyISAM 🚀(秒出结果) vs InnoDB 🐢(要扫描)
- 并发写入:MyISAM 😵(表锁阻塞) vs InnoDB 😎(行锁流畅)
- 数据安全:MyISAM 🚑(需定期修复) vs InnoDB 🛡️(自动恢复)
(✪▽✪)曼波~~ 现在主流都用InnoDB啦~就像大家现在更爱喝手冲咖啡!除非特殊需求(比如全文检索),否则推荐默认选InnoDB哦!
有哪些优化数据库性能的方法?
一、💡 SQL 优化三板斧
1. EXPLAIN 大法
EXPLAIN SELECT * FROM users WHERE age > 25 ORDER BY create_time;
-- 重点观察:type(扫描类型)、key(使用索引)、rows(扫描行数)
2. 索引优化技巧
- 给WHERE/ORDER BY/JOIN字段加索引
- 避免在索引列上做计算:
WHERE YEAR(create_time)=2023
❌ - 使用覆盖索引:
SELECT 索引字段
3. 慢查询日志分析
# my.cnf 配置
slow_query_log = 1
long_query_time = 1 # 超过1秒的查询
用mysqldumpslow
工具分析日志
二、🚀 结构设计优化
1. 三范式与反范式的平衡
- 适度冗余:减少JOIN次数
- 大字段分离:把TEXT/BLOB单独存表
2. 分区表实战
-- 按时间范围分区
CREATE TABLE logs (
id INT,
log_time DATETIME
) PARTITION BY RANGE (YEAR(log_time)) (
PARTITION p2022 VALUES LESS THAN (2023),
PARTITION p2023 VALUES LESS THAN (2024)
);
3. 冷热数据分离
- 热数据:最近3个月订单 → SSD存储
- 冷数据:历史订单 → HDD归档
三、⚙️ 配置调优示例
InnoDB 核心参数
innodb_buffer_pool_size = 70%内存 # 缓存池大小
innodb_flush_log_at_trx_commit = 2 # 平衡安全与性能
max_connections = 1000 # 根据实际调整
四、🛠️ 架构级优化
1. 读写分离
- 主库处理写操作
- 从库处理读查询
2. 缓存策略
import redis.clients.jedis.Jedis;
public class UserService {
private static final String REDIS_HOST = "localhost";
private static final int REDIS_PORT = 6379;
// 曼波小贴士:真实项目要用连接池哦!
public User getUser(String userId) {
try (Jedis jedis = new Jedis(REDIS_HOST, REDIS_PORT)) {
// 1. 先查缓存
String redisKey = "user:" + userId;
String cachedData = jedis.get(redisKey);
if (cachedData != null) {
return JSON.parseObject(cachedData, User.class); // 使用JSON库反序列化
}
// 2. 缓存未命中则查数据库
User user = jdbcTemplate.queryForObject(
"SELECT * FROM users WHERE id = ?",
new Object[]{userId},
new UserRowMapper()
);
// 3. 写入缓存(设置1小时过期)
if (user != null) {
jedis.setex(redisKey, 3600, JSON.toJSONString(user));
}
return user;
}
}
}
3. 分库分表
- 垂直分库:用户库、订单库分离
- 水平分表:user_001, user_002...
(✪▽✪)曼波~~ 记住优化要像中医把脉,先诊断(分析慢查询)再开方(针对性优化)!
如何定位慢查询?
一、🔍 基础定位三板斧
1. 慢查询日志捕获
-- 临时开启(重启失效)
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1; -- 超过1秒的查询
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';
-- 永久生效配置(my.cnf)
[mysqld]
slow_query_log = 1
long_query_time = 1
log_queries_not_using_indexes = 1 -- 记录未走索引的查询
2. 日志分析神器
# 查看最耗时的10个慢查询
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log
# 解析结果示例
Count: 5 Time=3.21s (16s) Lock=0.00s (0s) Rows=1000.0 (5000)
SELECT * FROM orders WHERE user_id=N
3. 实时监控SHOW PROCESSLIST
-- 查看正在运行的查询
SHOW FULL PROCESSLIST;
-- 重点关注:
State: "Sending data" -- 正在传输数据
Time: 大于100秒的查询 -- 可能卡住的查询
二、🔧 深度分析工具包
1. EXPLAIN 执行计划解读
EXPLAIN FORMAT=JSON
SELECT * FROM products
WHERE category='electronics'
ORDER BY price DESC;
-- 关键指标:
"access_type": "ALL" -- 全表扫描(危险!)
"rows_examined_per_scan": 10000 -- 扫描行数
"using_filesort": true -- 文件排序(需优化)
2. Performance Schema 监控
-- 开启性能监控
UPDATE performance_schema.setup_instruments
SET ENABLED = 'YES'
WHERE NAME LIKE '%statement/%';
-- 查询TOP SQL
SELECT DIGEST_TEXT, AVG_TIMER_WAIT
FROM performance_schema.events_statements_summary_by_digest
ORDER BY AVG_TIMER_WAIT DESC
LIMIT 10;
3. pt-query-digest 高级分析
# 使用Percona Toolkit
pt-query-digest /var/log/mysql/slow.log
-- 输出包括:
# Rank 响应时间占比
# Attribute 各SQL指纹
# Exec time 执行时间统计
三、🚀 Java生态专用方案
1. Druid 连接池监控
// Spring Boot配置
@Bean
public ServletRegistrationBean<StatViewServlet> druidServlet() {
return new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");
}
// 监控指标包括:
- SQL执行时间排行
- 慢SQL记录(支持配置阈值)
- 执行次数TOP SQL
2. MyBatis 打印慢SQL
<!-- mybatis-config.xml -->
<settings>
<setting name="defaultStatementTimeout" value="5"/> <!-- 超时5秒 -->
</settings>
<!-- 配合p6spy记录真实SQL -->
driverClassName=com.p6spy.engine.spy.P6SpyDriver
(✪▽✪)曼波~~ 定位到慢SQL后,记得用「EXPLAIN+SQL重写+索引优化」三连击哦!