- 1 首先我们找到mysql占比高的进程号PID
top
- 2 根据PID找到mysql的os_thread_id
top -H -p 2559
我们这里可以明显看到有个pid=16815的程序在占用cpu进程 那么我们找到这进行查询的慢sql
这里可以看到是哪个主机连接的信息
SELECTa. USER,a. HOST,a.db,b.thread_os_id,b.thread_id,a.id processlist_id,a.command,a.time,a.state,a.infoFROMinformation_schema. PROCESSLIST a,PERFORMANCE_SCHEMA .threads bWHEREa.id = b.processlist_idAND b.thread_os_id = 16804;
- 我们最终要的是sql 那么执行下面找个就可以找到高id的进程所属的sql
SELECT*FROMPERFORMANCE_SCHEMA.events_statements_currentWHEREthread_id = (SELECTthread_idFROMPERFORMANCE_SCHEMA .threadsWHEREthread_os_id = 16804) ;
接下来优化sql就行了
这里我们随意找一处比较耗时的sql来做统计
这应该是一位非常懂这块业务的哥们写的 我们来看一下
EXPLAINSELECT g.*FROM (SELECT DISTINCT ru.id AS unitId, ru.unit_name AS unitName, ru.create_time, ru.baseid, ru.entid, p.id AS postId, p.post_name AS postName, IFNULL(a.patrolNum, 0) AS patrolNum, IFNULL(ht.hiddenNum, 0) AS hiddenNum, b.postRiskLevel, b.postRiskLevelText, c.unitRiskLevel, c.unitRiskLevelTextFROM drh_risk_unit_post rupLEFT JOIN drh_risk_unit ru ON ru.id = rup.risk_unit_idLEFT JOIN ent_post p ON p.id = rup.post_idLEFT JOIN (SELECT COUNT(1) AS patrolNum, pp.post_idFROM drh_post_patrol ppGROUP BY pp.post_id) aON a.post_id = rup.post_idLEFT JOIN (SELECT COUNT(1) AS hiddenNum, h.post_idFROM drh_hidden hGROUP BY h.post_id) htON ht.post_id = rup.post_idLEFT JOIN (SELECT llt.*, dt.item_text AS postRiskLevelTextFROM (SELECT ht1.*FROM (SELECT a.*, rup.risk_unit_idFROM drh_risk_unit_post rupLEFT JOIN (SELECT MIN(hft.risk_level) AS postRiskLevel, pr.post_idFROM (SELECT hf.fk_id, MIN(hf.risk_level) AS risk_levelFROM drh_post_result_hazar_factors hfGROUP BY hf.fk_id) hftLEFT JOIN drh_post_result pr ON pr.id = hft.fk_idWHERE pr.post_id IS NOT NULLGROUP BY pr.post_id) aON a.post_id = rup.post_idLEFT JOIN drh_risk_unit ru ON ru.id = rup.risk_unit_idWHERE ru.unit_source = '1') ht1UNION ALLSELECT ht2.*FROM (SELECT a.*, rup.risk_unit_idFROM drh_risk_unit_post rupLEFT JOIN (SELECT MIN(hft.risk_level) AS postRiskLevel, sm.post_idFROM (SELECT hf.fk_id, MIN(hf.risk_level) AS risk_levelFROM drh_post_result_hazar_factors hfGROUP BY hf.fk_id) hftLEFT JOIN drh_safety_matters sm ON sm.id = hft.fk_idWHERE sm.post_id IS NOT NULLGROUP BY sm.post_id) aON a.post_id = rup.post_idLEFT JOIN drh_risk_unit ru ON ru.id = rup.risk_unit_idWHERE ru.unit_source = '2') ht2) lltLEFT JOIN sys_dict_item dt ON llt.postRiskLevel = dt.item_valueLEFT JOIN sys_dict d ON dt.dict_id = d.idWHERE d.dict_code = 'drh_inherent_risk_level') bON b.risk_unit_id = rup.risk_unit_idAND b.post_id = rup.post_idLEFT JOIN (SELECT tll.*, dt.item_text AS unitRiskLevelTextFROM (SELECT ull.risk_unit_id, MIN(ull.postRiskLevel) AS unitRiskLevelFROM (SELECT ht1.*FROM (SELECT a.*, rup.risk_unit_idFROM drh_risk_unit_post rupLEFT JOIN (SELECT MIN(hft.risk_level) AS postRiskLevel, pr.post_idFROM (SELECT hf.fk_id, MIN(hf.risk_level) AS risk_levelFROM drh_post_result_hazar_factors hfGROUP BY hf.fk_id) hftLEFT JOIN drh_post_result pr ON pr.id = hft.fk_idWHERE pr.post_id IS NOT NULLGROUP BY pr.post_id) aON a.post_id = rup.post_idLEFT JOIN drh_risk_unit ru ON ru.id = rup.risk_unit_idWHERE ru.unit_source = '1') ht1UNION ALLSELECT ht2.*FROM (SELECT a.*, rup.risk_unit_idFROM drh_risk_unit_post rupLEFT JOIN (SELECT MIN(hft.risk_level) AS postRiskLevel, sm.post_idFROM (SELECT hf.fk_id, MIN(hf.risk_level) AS risk_levelFROM drh_post_result_hazar_factors hfGROUP BY hf.fk_id) hftLEFT JOIN drh_safety_matters sm ON sm.id = hft.fk_idWHERE sm.post_id IS NOT NULLGROUP BY sm.post_id) aON a.post_id = rup.post_idLEFT JOIN drh_risk_unit ru ON ru.id = rup.risk_unit_idWHERE ru.unit_source = '2') ht2) ullGROUP BY ull.risk_unit_id) tllLEFT JOIN sys_dict_item dt ON tll.unitRiskLevel = dt.item_valueLEFT JOIN sys_dict d ON dt.dict_id = d.idWHERE d.dict_code = 'drh_inherent_risk_level') cON c.risk_unit_id = rup.risk_unit_id) gWHERE g.postRiskLevelText IS NOT NULLAND g.entid = 1AND g.baseid = 1ORDER BY g.create_time DESCLIMIT 10;
耗时22秒 接下来我们分析下
我们通过分析得出 这里面的tablederived2 的rows是一个笛卡尔积 他的数量等于id=2的所有操作 ,其实通过sql可以看出这里不难得出子查套子查询 导致查询效率低
一个主表 left 两个子查询后 外面又套了一个子查询
意思是 子查询 套子查询 导致查询结果比较慢,那么我们就这样优化 如下
SELECT DISTINCT ru.id AS unitId, ru.unit_name AS unitName, ru.create_time, ru.baseid, ru.entid, p.id AS postId, p.post_name AS postName, IFNULL(a.patrolNum, 0) AS patrolNum, IFNULL(ht.hiddenNum, 0) AS hiddenNum, b.postRiskLevel, b.postRiskLevelText, c.unitRiskLevel, c.unitRiskLevelTextFROM drh_risk_unit_post rupLEFT JOIN drh_risk_unit ru ON ru.id = rup.risk_unit_idLEFT JOIN ent_post p ON p.id = rup.post_idLEFT JOIN (SELECT COUNT(1) AS patrolNum, pp.post_idFROM drh_post_patrol ppGROUP BY pp.post_id) aON a.post_id = rup.post_idLEFT JOIN (SELECT COUNT(1) AS hiddenNum, h.post_idFROM drh_hidden hGROUP BY h.post_id) htON ht.post_id = rup.post_idLEFT JOIN (SELECT llt.*, dt.item_text AS postRiskLevelTextFROM (SELECT ht1.*FROM (SELECT a.*, rup.risk_unit_idFROM drh_risk_unit_post rupLEFT JOIN (SELECT MIN(hft.risk_level) AS postRiskLevel, pr.post_idFROM (SELECT hf.fk_id, MIN(hf.risk_level) AS risk_levelFROM drh_post_result_hazar_factors hfGROUP BY hf.fk_id) hftLEFT JOIN drh_post_result pr ON pr.id = hft.fk_idWHERE pr.post_id IS NOT NULLGROUP BY pr.post_id) aON a.post_id = rup.post_idLEFT JOIN drh_risk_unit ru ON ru.id = rup.risk_unit_idWHERE ru.unit_source = '1') ht1UNION ALLSELECT ht2.*FROM (SELECT a.*, rup.risk_unit_idFROM drh_risk_unit_post rupLEFT JOIN (SELECT MIN(hft.risk_level) AS postRiskLevel, sm.post_idFROM (SELECT hf.fk_id, MIN(hf.risk_level) AS risk_levelFROM drh_post_result_hazar_factors hfGROUP BY hf.fk_id) hftLEFT JOIN drh_safety_matters sm ON sm.id = hft.fk_idWHERE sm.post_id IS NOT NULLGROUP BY sm.post_id) aON a.post_id = rup.post_idLEFT JOIN drh_risk_unit ru ON ru.id = rup.risk_unit_idWHERE ru.unit_source = '2') ht2) lltLEFT JOIN sys_dict_item dt ON llt.postRiskLevel = dt.item_valueLEFT JOIN sys_dict d ON dt.dict_id = d.idWHERE d.dict_code = 'drh_inherent_risk_level' )bON b.risk_unit_id = rup.risk_unit_idAND b.post_id = rup.post_idLEFT JOIN ( SELECT tll.*, dt.item_text AS unitRiskLevelTextFROM (SELECT ull.risk_unit_id, MIN(ull.postRiskLevel) AS unitRiskLevelFROM (SELECT ht1.*FROM (SELECT a.*, rup.risk_unit_idFROM drh_risk_unit_post rupLEFT JOIN (SELECT MIN(hft.risk_level) AS postRiskLevel, pr.post_idFROM (SELECT hf.fk_id, MIN(hf.risk_level) AS risk_levelFROM drh_post_result_hazar_factors hfGROUP BY hf.fk_id) hftLEFT JOIN drh_post_result pr ON pr.id = hft.fk_idWHERE pr.post_id IS NOT NULLGROUP BY pr.post_id) aON a.post_id = rup.post_idLEFT JOIN drh_risk_unit ru ON ru.id = rup.risk_unit_idWHERE ru.unit_source = '1') ht1UNION ALLSELECT ht2.*FROM (SELECT a.*, rup.risk_unit_idFROM drh_risk_unit_post rupLEFT JOIN (SELECT MIN(hft.risk_level) AS postRiskLevel, sm.post_idFROM (SELECT hf.fk_id, MIN(hf.risk_level) AS risk_levelFROM drh_post_result_hazar_factors hfGROUP BY hf.fk_id) hftLEFT JOIN drh_safety_matters sm ON sm.id = hft.fk_idWHERE sm.post_id IS NOT NULLGROUP BY sm.post_id) aON a.post_id = rup.post_idLEFT JOIN drh_risk_unit ru ON ru.id = rup.risk_unit_idWHERE ru.unit_source = '2') ht2) ullGROUP BY ull.risk_unit_id) tllLEFT JOIN sys_dict_item dt ON tll.unitRiskLevel = dt.item_valueLEFT JOIN sys_dict d ON dt.dict_id = d.idWHERE d.dict_code = 'drh_inherent_risk_level' ) cON c.risk_unit_id = rup.risk_unit_idWHERE b.postRiskLevelText IS NOT NULLand ru.entid = 1and ru.baseid = 1ORDER BY ru.create_time DESCLIMIT 10
我们这里验证一下是否是这样
通过验证我们发现1.多秒就执行完了 原先需要20秒
早cpu高峰的时候
1 通过top命令找到那台机器连接我们的mysql比较耗CPU
2 通过 top -H -p PID 找到我们mysql那个物理进程比较耗费cpu
然后根据sql找到当时执行的sql或者是
找到我们的后台程序对应的数据库监控工具进行查询哪些比较慢
我的web后台使用到了druid 通过druid监控也可以查询到一些慢查询的sql
参考:https://www.isolves.com/it/sjk/MYSQL/2022-03-11/51075.html
http://www.muzhuangnet.com/show/44458.html
http://t.zoukankan.com/wyy123-p-9258513.html
https://blog.csdn.net/asd051377305/article/details/113979657