性能度量标准
- QPS
- TPS
- RT
问题来源
- 慢日志,配置参数(MySQL5.7)
slow_query_log=1
long_query_time=0.5
slow_query_log=slow.log
- tcpdump & wireshark
tcpdump -nvvv -i eth0 -c 20 'port 3306 and host x'
- 监控告警 例如接口的SLA告警TP99
分析慢在哪里
性能分析profiling
sequenceDiagram
应用(JDBC)->>服务端: 创建连接
应用(JDBC)->>服务端: 发送SQL:select name from tb1 where id = 888
服务端->>应用(JDBC): FetchSize 结果集
应用(JDBC)->>服务端: 断开连接
定位每步的开销
set profiling=1;
show profiles;
show profile for query 1;
Profile在5.7和8版本已经被标记为废弃,官方建议使用Performance Schema进行性能分析,后续补充
执行计划explain
- type:const>eq_ref>ref>ref_or_null>range>index>all
select * from tb1 where id = 1;
select a.name from tb1 a left join tb2 b where a.id = b.id;
select * from tb1 where name='san';
select * from tb1 where name='san' or name is null;
select * from tb1 where age > 20 and age < 30;
select name from tb1;
select * from tb1;
- rows:检索的行数
- extra:
- using where
- using index
- using index condition
- using filesort
- using temporary
- using index for group by
- using join buffer
最佳实践:
- select
- 查询尽量走索引,走覆盖索引,走组合索引的最左前缀
- 避免select *
- 避免结果集数据量过大
- 避免在过滤和排序字段进行函数运算
- 避免类型转换
- join
- 小表驱动大表
- 连接字段走索引且类型匹配(不匹配会全表扫)
- 优先优化nested-loop内层循环
- 避免交叉连接(笛卡尔积)
- limit 注意offset问题
select * from tb1 limit 100000,10;
select * from tb1 t1,(select id from tb1 order by id limit 100000,10) t2 where t1.id = t2.id limit 10;
select * from tb1 where id > $max_id order by id limit 10;
- order by
- group by
- 松散索引扫描,完全利用索引查询数据再分组
- 紧凑索引扫描,区别在于索引扫描时,读取所有满足条件的索引键,然后再根据读取的数据分组
- 建立避免临时表排序
- count,建议count(*)/count(1),而count(field) 不统计null值,精确度要求不高使用information_schama.table的统计信息
- DML
- 大操作 -> 批量小操作,避免锁竞争和复杂延迟
- 注意操作顺序,防止Dead Lock
- 全表数据清理,建议使用truncate,注意自增键会重置
- DDL(同一个表的操作合并,online DDL,第三方在线改表)
表结构
- engine选择
- 字段设计
- 越小越好,例如ip使用inet_aton函数转成unsigned int,用4个字节即可,电话号码bigint > varchar
- 越简单越好
- not null 好于 null
- tinyint 好于 enum
- char,varchar 好于 blob,text
- 拆分表
- 垂直拆分:冷热分离,text\blob单独放表
- 水平扩展,引入中间件分库分表
- 索引
- 建议自增id作为主键
- 不建议使用md5,无序字符串作为主键,因为插入数据会导致频繁分页,占用空间大,查询性能差
- 出现在where\join关联字段\order by\group by中的字段适合建索引
- 更新频繁的字段不建议建索引,影响性能
- 基数不高的列不建议建索引
- 组合索引,按区分度从左到右
- 组合索引字段,不建议超过5个
- 建议使用短索引,长字符串进行截取使用前缀索引,既能优化查询,又避免了索引过大
- 单表不建议建超过5个索引
- 不要建冗余索引
代码
- 使用预编译语句,防止SQL注入,提升性能
- MyBatis一、二级缓存
数据库配置(主从、参数)
- 读写分离
- 同步方式
主机配置
提升配置,磁盘扩容,倍增扩库等
网络状况
分析网络耗时
加缓存
查询类占比多的情况,引入ehcache+redis等,做自己擅长的事务操作