V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
fenguxnyu
V2EX  ›  程序员

[求助] 一个 SpringBoot+Mysql 项目的性能优化问题

  •  
  •   fenguxnyu · 2020-01-09 15:13:35 +08:00 · 3048 次点击
    这是一个创建于 1540 天前的主题,其中的信息可能已经有所发展或是发生改变。

    请教大家一个关于 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 分钟。

    大家遇到过这种情况么,有什么解决办法可以参考吗?

    第 1 条附言  ·  2020-01-09 17:43:14 +08:00

    数据库开启了慢查询,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 |

    15 条回复    2020-01-10 10:41:52 +08:00
    cheng6563
        1
    cheng6563  
       2020-01-09 16:53:28 +08:00 via Android   ❤️ 1
    是不是有内存泄露,有虚拟内存吗
    wshcdr
        2
    wshcdr  
       2020-01-09 17:12:50 +08:00
    关注这个问题
    phantomzz
        3
    phantomzz  
       2020-01-09 17:15:05 +08:00
    把你们表结构,索引、以及你的查询 sql 发出来。
    phantomzz
        4
    phantomzz  
       2020-01-09 17:16:52 +08:00
    检查你们的 sql 有没有导致全表扫描
    fenguxnyu
        5
    fenguxnyu  
    OP
       2020-01-09 17:21:53 +08:00
    @phantomzz explain 看了下,没有哦,如果有的话,慢查询日志应该要记录到啊
    luozic
        6
    luozic  
       2020-01-09 17:28:14 +08:00
    上全流程 metric,查看一下是哪里慢了,现在这描述不清楚是数据库慢,还是 Hibernate 慢,还是代码慢。
    fenguxnyu
        7
    fenguxnyu  
    OP
       2020-01-09 17:45:06 +08:00
    @luozic 改成 jdbcTemplate 使用裸 sql 去查,还是一样的问题;如果慢查询日志没有大于 1000 毫秒的记录,是不是可以证明 mysql 那端没有大问题?
    pmispig
        8
    pmispig  
       2020-01-09 17:49:23 +08:00
    用 skywalking 和阿里的阿尔萨斯,但是在这里我要黑一下 skywalikng 的作者太傲慢,以及它在 es 的数据结构太傻逼
    luozic
        9
    luozic  
       2020-01-09 18:16:37 +08:00
    @fenguxnyu 这两个接口是否只是查询?
    lewis89
        10
    lewis89  
       2020-01-09 18:25:16 +08:00
    本地用 jprofiler 试试 可以看每个方法的调用时间
    phantomzz
        11
    phantomzz  
       2020-01-09 19:06:32 +08:00
    检查你索引的结构,你的索引是不是宽索引,有没有导致回表,联合索引和你的 sql 是否匹配,比如是否符合前缀匹配
    Raymon111111
        12
    Raymon111111  
       2020-01-09 19:08:20 +08:00
    额外看一下 gc 和 jstack

    当 A 查询需要好几千 ms 的时候用语句直接上 mysql 的 server 执行一下看看需要多久
    zrc
        13
    zrc  
       2020-01-09 22:01:52 +08:00
    arthas 可以追查到那个地方耗时比较高
    两个 sql 返回的数据量有多大?
    我觉得还是有必要看下 gc 和堆栈,感觉像是有地方大量引用了数据,导致 gc 回收效率很低
    fenguxnyu
        14
    fenguxnyu  
    OP
       2020-01-10 10:40:45 +08:00
    @zrc gc 和堆栈看起来也没什么异常,A 查询出来的记录就一条,B 查询出来的数据量 5 条左右。
    fenguxnyu
        15
    fenguxnyu  
    OP
       2020-01-10 10:41:52 +08:00
    @luozic 只是查询
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   971 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 20:20 · PVG 04:20 · LAX 13:20 · JFK 16:20
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.