1. mysql 索引合并优化
索引合并(Index Merge)是 MySQL 在无法使用单个索引高效完成查询时,尝试同时使用多个单列索引,把结果集合并后返回的执行策略。它本质上是一个“折中”:能救就救,但远不如一个真正能覆盖查询条件的复合索引高效。
Index Merge = 同时扫描多个(单列)索引的范围结果,然后用 union/intersection 做集合运算合并结果。
典型合并方式:
SELECT * FROM user
WHERE age > 20 AND status = 1;
如果你只有:
idx_age(age)
idx_status(status)
但没有 (status, age) 这样的复合索引,MySQL 就可能选择:index merge: intersection(idx_age, idx_status)
Index Merge 的问题
很多人以为“多个索引一起用”很厉害,结果反而掉坑里。
1. 合并需要额外 CPU + 内存
扫描两个索引结果,再做集合运算 → 并不便宜。
2. 回表次数可能变多
Index Merge 合并后得到大量主键 ID,再根据这些 ID 回表 → IO 打爆。
3. 远不如一个合适的复合索引
复合索引可以:
- 顺序扫描
- 直接过滤更多行
- 最小化回表
- 可以覆盖查询
Index Merge 全都做不到。
所以 InnoDB 开发人员自己都说:Index Merge 是 suboptimal,但 better than full table scan。比全表扫稍微好一点,但离最佳方案还差远。
要有的认知:
- Index Merge 是 MySQL 给你“兜底”的,不是奖励,不是优化,是 无奈。
- EXPLAIN 出现了它,意味着:你的索引设计不够好。
- 最强组合永远是:复合索引 + 覆盖索引 + 合理的 where 组织结构
2. redis 大 value危害
1. 阻塞 Redis 单线程,导致 QPS 急剧下降
Redis 是单线程处理命令的,大 value 的读写会让处理时间显著变长。
- GET一次要反序列化一个巨大的字符串/对象 → 阻塞主线程
- SET一个大 value → 阻塞主线程
- HGETALL 一个超大 hash → 阻塞主线程
大 value 会放大 Redis 的单线程劣势。同一实例上所有请求都会卡住。
典型事故:某个 1MB 的 value 被频繁更新,Redis CPU 飙满,其他 key 都访问超时。
2. 网络传输开销巨大
你把 500KB 或 1MB 的东西从 Redis 拿出来意味着:
- TCP 从 Redis 传到你的 Java 应用
- Java 反序列化,再 GC
- 业务线程卡顿
平均延迟会从 1ms → 几十到几百 ms。
3. 带来明显的内存碎片率
Redis 内部使用 jemalloc 管理内存,大 value 导致:
- 内存分配不均匀
- 页面占用不规则
- 内存碎片率可能到 1.5~2
也就是说你申请了 10GB,可能只有 5~7GB 是有效数据。
4. AOF/RDB 持久化时间会急剧上升
大 value 持久化成本更高:
- RDB 生成耗时更久 → 可能阻塞
- AOF rewrite 写入慢、文件巨大 → I/O 压力增加
甚至影响 Redis 的可用性。
5. 主从同步变慢甚至中断
Redis 主从复制是全量传输数据的。
如果你有大量大 value:
- 同步时需要巨大网络带宽
- 延迟上升
- 从库与主库GAP拉大,甚至丢失同步
主从切换也会变得更慢、更不稳定。
6. Java 端序列化/反序列化开销陡增
你是 Java 工程师,这一条你很快就会体会:
- Spring Cache 从 Redis 拿一个超大的 JSON
- ObjectMapper.readValue
解一个几百 KB 的结构
- Young GC、Old GC 都会上升
- RT 突刺,特别是高峰期
value 大小
影响程度
说明
> 10KB
可接受
建议优化,但问题不大
> 100KB
明显问题
网络 + CPU + 内存 都开始痛
> 1MB
高危
线上应禁止
> 5MB
致命
单个 key 就是一个雷
怎么处理?
- 拆分value
- 大数据放 ES、MySQL,不要放 Redis
- 使用压缩,但注意 CPU 开销,zip等等。
3. mysql ssd带来的性能提升
顺序读写:提升并不夸张
顺序 IO 对 HDD 其实不差,HDD 200+ MB/s,SSD 几百 MB/s 到几 GB/s。能提升,但不是核心。
随机 IO:质的飞跃(核心价值)
MySQL 的真实工作模式:
- 随机读 page
- 随机读写 undo
- 随机写 redo
- 随机写 B+ 树节点
随机 IO 在 HDD 上是灾难:
- HDD:100 IOPS 左右
- SSD:5 万 ~ 50 万 IOPS
这是 几百倍到几千倍 的差距。MySQL 绝大部分延迟,都卡在随机 IO 上,而 SSD 正好砍掉了这条链路。
结论:SSD 对 MySQL = 从拖拉机换成超跑。
但 SSD 不是救命稻草。 SSD 也拯救不来糟糕 SQL 。
SSD 给你带来的本质收益是什么?即:把 IO 从“问题中心”变成“影响较小的因素”,让你能把精力放回业务与 SQL 上。
在 HDD 时代,架构策略都是为了“避开 IO”;
在 SSD 时代,你终于能“正视 IO 而不是绕开 IO”。
4. 降级
降级的本质是保底。例如查询接口,新加了一个查询条件,当系统不稳定时,我们优先确保系统能够查到数据(即使条件不全)。若因为新条件不可用就返回空,相当于是次要功能(新增的条件)阻塞了主要功能(查询)。即有损服务但是绝不崩溃。