Java 写的一个接口, CPU 满载下只有 12 并发量......,如何改善 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
337136897
1.07D
V2EX    程序员

Java 写的一个接口, CPU 满载下只有 12 并发量......,如何改善

  •  
  •   337136897 2018-10-31 10:08:59 +08:00 5927 次点击
    这是一个创建于 2544 天前的主题,其中的信息可能已经有所发展或是发生改变。

    同事写的一个接口。就是查询评论这一块的,同时查询 6 张表吧。用阿里云服务器 4 核 8G 的,CPU 满载,并发只有 12。对,没错只有 12.然后我发现 mysqld 这个进程使用 cpu85%, 剩下的 15%才给了 JVM。 应该怎么去优化这个接口,12 并发是不给活啊

    第 1 条附言    2018-10-31 14:35:13 +08:00

    SQL贴上来吧,总共有

    SELECT A.*,B.headIcon from `comt_like`AS A left join (select userCode,headIcon FROM user_info) as B on A.userCode = B.userCode where commentCode in ( select commentCode FROM `comt_parent` where disType = #{disType} ) ORDER BY commentCode,operationTime select * FROM `comt_parent_image` where commentCode in ( select commentCode FROM `comt_parent` where disType = #{disType} ) select * from (select DISTINCT A.*,C.nickName,C.headIcon,IFNULL(b.num,0) as childReplyCount from `comt_child` as A left join (select parentCode,count(1) as num from `comt_child` where parentCode is not null group by parentCode) as B on A.childCode = B.parentCode left join (select userCode,headIcon,nickName FROM user_info) as C on A.userCode = C.userCode where commentCode in ( select commentCode FROM `comt_parent` where disType = #{disType}) ORDER BY commentCode,childReplyCount DESC,createTime DESC) T GROUP BY T.commentCode select A.*,D.nickName,D.headIcon,E.themeName, ifnull(B.childCount,0) as childCount,ifnull(C.likeCount,0) as likeCount, childCount+likeCount as sumCount, (select userCode from `comt_like` where userCode = #{loginUserCode} and commentCode = A.commentCode) as isLike from comt_parent as A left join (select commentCode,count(commentCode) as childCount,parentCode from comt_child group by commentCode) AS B on A.commentCode = B.commentCode left join (select commentCode,count(commentCode) as likeCount from comt_like group by commentCode) AS C on A.commentCode = C.commentCode left join (select nickName,userCode,headIcon from user_info) as D on A.userCode = D.userCode left join (select id,themeName from comt_theme) as E on A.themeId = E.id where A.disType = #{disType} and A.commentType = 2 order by sumCount DESC 

    一共这几条,谢谢

    第 2 条附言    2018-10-31 14:44:07 +08:00

    表的结构在这儿

    mysql> desc comt_like; +------------- | Field +---------------+----------- | id | bigint(20) | commentCode | varchar(255) | userCode | varchar(255) | | operationTime | datetime mysql> desc comt_parent; +--------------------+------------- | Field | Type +--------------------+------------ | id | bigint(20) | commentCode | varchar(255) | userCode | varchar(255) | createTime | datetime | text | longtext | disType | int(11) | indexCode | varchar(255) | themeId | varchar(255) | detailedName | varchar(255) | productDescription | varchar(255) | isPrize | int(11) unsigned | commentType | int(11) mysql> desc comt_parent_image; +-------------+-------- | Field | Type +-------------+----------- | id | bigint(20) | imageCode | varchar(255) | commentCode | varchar(255) | imageUrl | varchar(255) | | imageIndex | varchar(255) | mysql> desc comt_child; +----------------+----------- | Field | Type +----------------+-------------- | id | bigint(20) | | childCode | varchar(255) | | parentCode | varchar(255) | | commentCode | varchar(255) | | userCode | varchar(255) | | text | varchar(999) | | createTime | datetime | parentIsDelete | int(11) | | childIsDelete | int(11) | | parentIsRead | int(11) | | childIsRead | int(11) | 
    54 条回复    2018-11-01 10:56:18 +08:00
    JavaFirstMaster
        1
    JavaFirstMaster  
       2018-10-31 10:12:20 +08:00
    mysql 占用那么高,那就是 mysql 语句需要优化了呀.需要同时查 6 张表是否考虑一下数据结构或者业务逻辑是否合理
    337136897
        2
    337136897  
    OP
       2018-10-31 10:13:31 +08:00
    @JavaFirstMaster 大佬 数据结构从哪方面去分析?给个联系方式请教下行否
    leriou
        3
    leriou  
       2018-10-31 10:15:12 +08:00
    如果是真的查询量特别多, 就把数据预处理到 nosql , 从 nosql 查
    krisbai
        4
    krisbai  
       2018-10-31 10:17:11 +08:00
    把慢查询日志打开看看
    zidian9
        5
    zidian9  
       2018-10-31 10:17:34 +08:00
    查询尽可能不要连表查,可以先查一张表,再通过键 in 的方法查别的表,在程序里写逻辑组装数据。
    另外做好 db 索引。
    glacer
        6
    glacer  
       2018-10-31 10:18:13 +08:00
    1. SQL 语句优化
    2. 加缓存
    jbiao520
        7
    jbiao520  
       2018-10-31 10:18:46 +08:00
    mysql cpu 高的话那估计是慢查询了,找找 sql 问题,是不是没建索引啊
    337136897
        8
    337136897  
    OP
       2018-10-31 10:19:36 +08:00
    @jbiao520 数据不多,同事已经建了索引了
    337136897
        9
    337136897  
    OP
       2018-10-31 10:22:00 +08:00
    @leriou 就是 mongo 或者 redis?
    lhx2008
        10
    lhx2008  
       2018-10-31 10:28:18 +08:00 via Android
    第一次查询把数据加到 redis 里面缓存,有新评论进来再把缓存删掉,这样几百个查询并发都没问题
    sun1991
        11
    sun1991  
       2018-10-31 10:41:44 +08:00
    @zidian9 查询尽可能不要连表查,可以先查一张表,再通过键 in 的方法查别的表
    --- 经常看到这种讲法, 自己做表连接的效率比 MYSQL 要高? 是不是说 MYSQL 这块儿的优化做得特别差?
    337136897
        12
    337136897  
    OP
       2018-10-31 10:42:38 +08:00
    @sun1991 那应该咋整
    zhaishunqi
        13
    zhaishunqi  
       2018-10-31 10:51:22 +08:00
    先试试 sql 优化吧...
    先通过条件过滤数据量大的表,作为一张虚拟表,然后再用数据量不大的表和过滤出来的结果进行联查试试吧.
    当然关键的检索字段加索引,但是也不要太多索引.
    实在不行,考虑下重新设计这部分的功能吧.
    eslizn
        14
    eslizn  
       2018-10-31 10:51:31 +08:00
    @sun1991 +1,合理利用好索引,避免笛卡尔积的情况下 连表查比分开多次查效率要高的多
    teddy2725
        15
    teddy2725  
       2018-10-31 10:56:16 +08:00
    买个 rds, 优化下 sql,cpu 占用这么高估计是 join 多了,索引设计不合理
    wysnylc
        16
    wysnylc  
       2018-10-31 11:17:13 +08:00
    拆分多表 sql 为单表,使用 parallelStream 或者 CompleTableFuture 推荐)进行并行执行
    去 join 和并行执行才能从代码上提高效率,其他的都是硬件提高导致性能提高而已
    leriou
        17
    leriou  
       2018-10-31 11:20:12 +08:00   1
    @337136897 现代业务方向是将业务放要使用的数据提前准备好, 准备方式是离线计算+实时计算, 尤其是多表查询用到的数据, 后台实时计算出来存储到 nosql 层, 前台业务的读请求只走 nosql, mysql 这种只对核心的关键业务开发, 大部分业务触及不到 mysql, 需要使用的数据预先处理到缓存层
    neoblackcap
        18
    neoblackcap  
       2018-10-31 11:30:33 +08:00
    @sun1991 +1,不看查询计划,不看索引情况,上来直接禁止 JOIN,分表查询,上 nosql。这大概是 V2EX 数据库调优的政治正确。

    @337136897 我觉得你调优先看慢查询定位问题。如果查询问题都不大,就是机器性能不行就提高 rds 实例性能。
    e9e499d78f
        19
    e9e499d78f  
       2018-10-31 11:31:18 +08:00 via iPhone   2
    开个 ssh 让那个谁上去看看
    micean
        20
    micean  
       2018-10-31 11:35:44 +08:00
    没有表结构、没有数据量、也没有 sql ……
    你们也能给这么多意见……
    337136897
        21
    337136897  
    OP
       2018-10-31 11:36:58 +08:00
    @wysnylc 老哥你说的这个我压根儿没听懂
    xmh51
        22
    xmh51  
       2018-10-31 11:39:51 +08:00
    数据量不大的情况下 索引作用不是很大,考虑 sql 有问题,你们看下 sql 的问题在哪吧。
    limuyan44
        23
    limuyan44  
       2018-10-31 11:40:07 +08:00 via Android
    现在真是什么都劝人上缓存,要不要再劝一下上分布式啊,建议 lz 把 sql 放上来,表结构也可以放上来研究研究。
    xmh51
        24
    xmh51  
       2018-10-31 11:42:32 +08:00
    mysql 可以监控出慢 sql 和查询的 sql。不会的话,手动排查
    排查思路:打出接口过程中执行的所有 sql,注意别漏了。
    先看下执行 sql 的条数,没问题的话 再一条一条 sql 拿出来使用 navcat 手动执行。看下问题点在哪。
    limuyan44
        25
    limuyan44  
       2018-10-31 11:42:42 +08:00 via Android
    还有数据量执行计划这些都可以放上来,不然只能瞎猜。
    Raymon111111
        26
    Raymon111111  
       2018-10-31 11:48:58 +08:00
    没有场景怎么优化

    先看看 sql 和数据量吧
    wysnylc
        27
    wysnylc  
       2018-10-31 12:02:05 +08:00
    @337136897 #21 并行,异步编程,详情百度
    no1xsyzy
        28
    no1xsyzy  
       2018-10-31 12:23:46 +08:00
    explain <查询语句>
    no1xsyzy
        29
    no1xsyzy  
       2018-10-31 12:29:12 +08:00
    @zidian9 这两个其实做了同样的运算,除非你用了 SELECT * 并连了不该连的表。
    顺便,注意删除所有 SELECT *,要啥写啥,不要 SELECT 多个列后再丢弃(同时,抛弃没有对此优化的 ORM )。
    jimrok
        30
    jimrok  
       2018-10-31 12:52:10 +08:00
    初步的想法是你上 memcached,查询一个评论,然后放入 memcachd 里,如果有新评论,过期这个 cache。或者你就将数据库做一个 slave,阿里云有读写分离的地址,你查询走读写分离地址,这样查询请求会被打到 slave 服务器。slave 服务器按照流量收费。另外要把 slave 的配置提高一些,防止复制延迟。
    misaka19000
        31
    misaka19000  
       2018-10-31 12:56:06 +08:00 via Android   1
    为什么都在推荐上缓存?第一步不应该是优化 SQL 找到 MySQLCPU 占用率高的原因吗
    bobuick
        32
    bobuick  
       2018-10-31 13:13:45 +08:00
    sql 肯定是需要优化了。
    优化到没办法了,就用拆分大法了。一些聚合,排序,联表过滤到逻辑可以放到程序里来做
    Hancock
        33
    Hancock  
       2018-10-31 13:18:42 +08:00
    优化索引,数据库读写分离
    qiyuey
        34
    qiyuey  
       2018-10-31 13:19:00 +08:00   1
    @sun1991 我的理解是,第一次的查询,和第二次的 in,都可以走缓存不走 DB,极大的减轻了 DB 的压力
    opengps
        35
    opengps  
       2018-10-31 13:19:07 +08:00
    别只看 cpu,数据库这种应用,你硬盘是 ssd 吗?大部分是因为硬盘的读写,让系统去等待了。
    还有个地方要注意,cpu100%并不意味着能正常干活,而是总资源已经不够分的了
    kran
        36
    kran  
       2018-10-31 13:23:13 +08:00 via iPhone
    显然首先是优化表结构
    ragnaroks
        37
    ragnaroks  
       2018-10-31 13:33:23 +08:00
    @opengps +1
    帮助多家微小企业优化过 DB,基本都是磁盘 IO 不足(阿里云 30M)
    337136897
        38
    337136897  
    OP
       2018-10-31 14:36:45 +08:00
    cgpiao
        39
    cgpiao  
       2018-10-31 14:38:55 +08:00
    这么一说我很担心 我写的 php 接口,laravel 写的,连接了 7,8 个表,还有子查询什么的。
    Le4fun
        40
    Le4fun  
       2018-10-31 15:03:24 +08:00
    你这 sql 一大坨 瞬间不想看了
    neoblackcap
        41
    neoblackcap  
       2018-10-31 15:03:43 +08:00
    @337136897 你的表都是没有索引的吗?你都贴了这么多了,何不将慢查询日志跟 explain 语句得到的查询计划一起发上来
    337136897
        42
    337136897  
    OP
       2018-10-31 15:38:40 +08:00
    @neoblackcap 数据量不多吧。所以没建索引。慢查询没开,晚点儿我去开一下。explain 语句是在哪里看? - -
    jjwjiang
        43
    jjwjiang  
       2018-10-31 15:39:50 +08:00   1
    这么多回复就 @neoblackcap 一条靠谱的
    你倒是先确定是不是查询的问题呀……执行计划……查询日志
    再不济你把语句一个 block 一个 block 慢慢删减,看看哪部分有最大的改善,别一上来就猜原因呀
    realpg
        44
    realpg  
    PRO
       2018-10-31 15:42:15 +08:00
    一点数据库基础没有的还不会准备资料的从 0 开始提问学习 DB 优化
    weizhen199
        45
    weizhen199  
       2018-10-31 15:43:06 +08:00
    sql 优化,从 xjb 加索引开始
    neoblackcap
        46
    neoblackcap  
       2018-10-31 15:46:10 +08:00
    @337136897 数据量不多是多少啊,你前面说同事建了索引,这里又全部隐藏了。你们性能调优都是靠散弹枪编程啊?还是撞大运编程?
    explain 是 sql 语句啊,你 explain 一下你的 sql 语句就知道了,上面有人说了。再不行你先读 mysql 文档。
    软件工程软件工程,不要都是靠猜啊。大胆猜想,实证分析,小心验证!
    micean
        47
    micean  
       2018-10-31 16:12:26 +08:00
    粗看了下 sql
    很多的 in 都可以优化成关联查询
    group by 算数量的可以优化成缓存流程
    DISTINCT 这个看你的数据量了

    评论表为什么要拆成 2 张表
    akira
        48
    akira  
       2018-10-31 18:30:45 +08:00
    表结构的索引 补一下,然后每个语句的 explain 补一下
    akira
        49
    akira  
       2018-10-31 18:34:09 +08:00
    SELECT A.*,B.headIcon from `comt_like`AS A
    left join (select userCode,headIcon FROM user_info) as B // 这个优化反效果了,每次都会对 user_info 表取一次全表,放外层会更好
    on A.userCode = B.userCode
    where commentCode in (
    select commentCode FROM `comt_parent` where disType = #{disType}
    )
    ORDER BY commentCode,operationTime
    littlewing
        50
    littlewing  
       2018-10-31 19:14:54 +08:00
    1. mysql 的 join 就是残废的,性能特别差,不要用
    2. 不要用子查询
    veightz
        51
    veightz  
       2018-11-01 02:51:30 +08:00
    Java 一般都会 DAO 上再套 Manager 做缓存,不直接关联
    评论这种走量的数据后续肯定会做分表,不用 join 趁早出坑
    devtk
        52
    devtk  
       2018-11-01 08:08:41 +08:00
    数据库这块需要优化
    v2orz
        53
    v2orz  
       2018-11-01 09:47:41 +08:00
    @sun1991 #11

    现在普遍的说法是,DBMS 重点在存储,计算的工作尽量由应用做,尽管可能绝对效率不如 SQL 计算
    因为应用扩展、拆分、后续维护都更容易
    xhinliang
        54
    xhinliang  
       2018-11-01 10:56:18 +08:00
    其实大型 Web 后端应用里,很少有连表查询的需求了。
    甚至,索引都很少用,一般主键就够了。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2304 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 31ms UTC 01:16 PVG 09:16 LAX 18:16 JFK 21:16
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86