遇到这个问题,不能上来就要分库分表。
这样就是把最贵的方案排在了最前面。千万级这个量级, InnoDB的B+树还远没到极限。大部分慢查询不 是因为数据多,是因为查的方式有问题。
expalin执行计划分析
重点看type和rows。
- type是ALL那么就是走了全表扫描。tpye是index是全索引扫描;较好的是ref或range,说明走了索引且只扫描了需要的部分。
- rows估算扫描行数。同样的sql,没加索引前扫描了几百万,加了索引rows变成了几百。
- extra,using fileSort性能差,它表示在内存中进行二次排序。
Explain Analyze
如果expalin看不出来什么,可以使用Explain Analyze,可以看到具体耗时和执行过程。
Select * 大表性能杀手
产生回表,大表中查出来的数据主键大概率物理页 不连续,所以这样会导致大量磁盘IO。
这个时候,使用覆盖索引,避免回表,性能提升好几倍!
深分页问题
limit m,n ; mysql执行方式是先扫描m行,然后丢弃m-n行,返回n行。前面m-n行的IO全是浪费。
优化方案是使用游标,减少返回行数;避免回表,减少IO次数
冷热归档和数据分批处理
最直接的做法是按时间归档。把三个月前的数据搬 到归档表,主表只留近期数据。搬完之后主表从两千万行瞬间缩到几百万,索引重建一遍,B+树层高可能直接降一级。
定时任务
搬迁可以用定时任务,每天凌晨跑一批:
分批操作很重要。一次性 DELETE几百万行会产 生巨大的事务日志,锁表时间长,从库同步也会延 迟。每次 LIMIT 10000,循环跑到没数据为止。
归档之后,偶尔需要查历史数据的需求,直接查归档表,不影响主表性能。
分库分表
分库分表排在最后面,不是排在最前面
索引调过了、查询改过了、冷数据归档了、深度分 页优化了、COUNT(*)也缓存了—做到这一步还 是慢,才轮到分区表或者分库分表。
分库分表的工程代价很实在:跨分片 JOIN 做不 了、分布式事务要上Saga或2PC、全局ID要换 Snowflake、数据迁移要双写方案。千万级这个量 级,绝大部分系统在前面几步就能解决问题,根本 走不到需要分表的那一步。