请教大家一个关于 SpringBoot+Mysql 项目的性能问题。
这边有一个被压测的方法里有两段代码分别是对数据库 A、B 两个表的访问,A 表和 B 表的 Where 条件字段分别加了索引 /联合索引;在每段代码块的前后都打上了计时统计日志,分别记为 LogA 和 LogB;访问数据库用的 Spring JPA+Hibernate,使用了连接池技术初始 50 个链接,最大连接数 500 ; Mysql 版本 8.0。
在压测时发现数据库请求代码块 L 的耗时统计 LogA 会随着压测时间越来越长,一开始是几十 ms,慢慢的上百 ms,最后达到几千 ms ; LogB 大部分是几十 ms,偶尔飙到几百毫秒;导致最后整个接口的 TPS 一百都不到
其中: A 表数量级:30 万条记录
B 表:1 万左右
CPU 占用:维持在 30%以内
内存占用:3%以内
数据库的 max_connections 调整到了 1000
压测并发数是 100,持续 2 分钟。
大家遇到过这种情况么,有什么解决办法可以参考吗?
数据库开启了慢查询,long_query_time设为0.1s,能记录到一些100ms左右的慢查询,但没有大于1秒的慢查询记录。
A表查询语句:
select f1,f2,f3 from A where code= ? and latest = 1;
A表上为code和latest 创建了联合索引,explain显示使用了索引,其中f1,f2,f3要查的为业务字段;latest字段取值只有0和1,explain结果如下:
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
| 1 | SIMPLE | A | NULL | ref | index_code_latest | index_code_latest | 1023 | const | 1 | 10.00 | Using where |
B表查询语句 :
select id,f1,f2,...,f15 from B where match(f1) against (?) and latest = 1
B表f1是字段是一个text字段,在上面建立了全文索引,B表一共查询了15个字段;latest字段取值只有0和1;explain结果如下:
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
| 1 | SIMPLE | B| NULL | fulltext | ft_f1 | ft_f1 | 0 | const | 1 | 10.00 | Using where; Ft_hints: sorted |
1
cheng6563 2020-01-09 16:53:28 +08:00 via Android 1
是不是有内存泄露,有虚拟内存吗
|
2
wshcdr 2020-01-09 17:12:50 +08:00
关注这个问题
|
3
phantomzz 2020-01-09 17:15:05 +08:00
把你们表结构,索引、以及你的查询 sql 发出来。
|
4
phantomzz 2020-01-09 17:16:52 +08:00
检查你们的 sql 有没有导致全表扫描
|
6
luozic 2020-01-09 17:28:14 +08:00
上全流程 metric,查看一下是哪里慢了,现在这描述不清楚是数据库慢,还是 Hibernate 慢,还是代码慢。
|
7
fenguxnyu OP @luozic 改成 jdbcTemplate 使用裸 sql 去查,还是一样的问题;如果慢查询日志没有大于 1000 毫秒的记录,是不是可以证明 mysql 那端没有大问题?
|
8
pmispig 2020-01-09 17:49:23 +08:00
用 skywalking 和阿里的阿尔萨斯,但是在这里我要黑一下 skywalikng 的作者太傲慢,以及它在 es 的数据结构太傻逼
|
10
lewis89 2020-01-09 18:25:16 +08:00
本地用 jprofiler 试试 可以看每个方法的调用时间
|
11
phantomzz 2020-01-09 19:06:32 +08:00
检查你索引的结构,你的索引是不是宽索引,有没有导致回表,联合索引和你的 sql 是否匹配,比如是否符合前缀匹配
|
12
Raymon111111 2020-01-09 19:08:20 +08:00
额外看一下 gc 和 jstack
当 A 查询需要好几千 ms 的时候用语句直接上 mysql 的 server 执行一下看看需要多久 |
13
zrc 2020-01-09 22:01:52 +08:00
arthas 可以追查到那个地方耗时比较高
两个 sql 返回的数据量有多大? 我觉得还是有必要看下 gc 和堆栈,感觉像是有地方大量引用了数据,导致 gc 回收效率很低 |