- 1 首先我们找到mysql占比高的进程号PID <ps 我这里已经优化过了 所以占比较低>
top
- 2 根据PID找到mysql的os_thread_id
top -H -p 2559
我们这里可以明显看到有个pid=16815的程序在占用cpu进程 那么我们找到这进行查询的慢sql
这里可以看到是哪个主机连接的信息
SELECT
a. USER,
a. HOST,
a.db,
b.thread_os_id,
b.thread_id,
a.id processlist_id,
a.command,
a.time,
a.state,
a.info
FROM
information_schema. PROCESSLIST a,
PERFORMANCE_SCHEMA .threads b
WHERE
a.id = b.processlist_id
AND b.thread_os_id = 16804;
- 我们最终要的是sql 那么执行下面找个就可以找到高id的进程所属的sql
SELECT
*
FROM
PERFORMANCE_SCHEMA.events_statements_current
WHERE
thread_id = (
SELECT
thread_id
FROM
PERFORMANCE_SCHEMA .threads
WHERE
thread_os_id = 16804
) ;
接下来优化sql就行了
这里我们随意找一处比较耗时的sql来做统计
这应该是一位非常懂这块业务的哥们写的 我们来看一下
EXPLAIN
SELECT 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.unitRiskLevelText
FROM drh_risk_unit_post rup
LEFT JOIN drh_risk_unit ru ON ru.id = rup.risk_unit_id
LEFT JOIN ent_post p ON p.id = rup.post_id
LEFT JOIN (
SELECT COUNT(1) AS patrolNum, pp.post_id
FROM drh_post_patrol pp
GROUP BY pp.post_id
) a
ON a.post_id = rup.post_id
LEFT JOIN (
SELECT COUNT(1) AS hiddenNum, h.post_id
FROM drh_hidden h
GROUP BY h.post_id
) ht
ON ht.post_id = rup.post_id
LEFT JOIN (
SELECT llt.*, dt.item_text AS postRiskLevelText
FROM (
SELECT ht1.*
FROM (
SELECT a.*, rup.risk_unit_id
FROM drh_risk_unit_post rup
LEFT JOIN (
SELECT MIN(hft.risk_level) AS postRiskLevel, pr.post_id
FROM (
SELECT hf.fk_id, MIN(hf.risk_level) AS risk_level
FROM drh_post_result_hazar_factors hf
GROUP BY hf.fk_id
) hft
LEFT JOIN drh_post_result pr ON pr.id = hft.fk_id
WHERE pr.post_id IS NOT NULL
GROUP BY pr.post_id
) a
ON a.post_id = rup.post_id
LEFT JOIN drh_risk_unit ru ON ru.id = rup.risk_unit_id
WHERE ru.unit_source = '1'
) ht1
UNION ALL
SELECT ht2.*
FROM (
SELECT a.*, rup.risk_unit_id
FROM drh_risk_unit_post rup
LEFT JOIN (
SELECT MIN(hft.risk_level) AS postRiskLevel, sm.post_id
FROM (
SELECT hf.fk_id, MIN(hf.risk_level) AS risk_level
FROM drh_post_result_hazar_factors hf
GROUP BY hf.fk_id
) hft
LEFT JOIN drh_safety_matters sm ON sm.id = hft.fk_id
WHERE sm.post_id IS NOT NULL
GROUP BY sm.post_id
) a
ON a.post_id = rup.post_id
LEFT JOIN drh_risk_unit ru ON ru.id = rup.risk_unit_id
WHERE ru.unit_source = '2'
) ht2
) llt
LEFT JOIN sys_dict_item dt ON llt.postRiskLevel = dt.item_value
LEFT JOIN sys_dict d ON dt.dict_id = d.id
WHERE d.dict_code = 'drh_inherent_risk_level'
) b
ON b.risk_unit_id = rup.risk_unit_id
AND b.post_id = rup.post_id
LEFT JOIN (
SELECT tll.*, dt.item_text AS unitRiskLevelText
FROM (
SELECT ull.risk_unit_id, MIN(ull.postRiskLevel) AS unitRiskLevel
FROM (
SELECT ht1.*
FROM (
SELECT a.*, rup.risk_unit_id
FROM drh_risk_unit_post rup
LEFT JOIN (
SELECT MIN(hft.risk_level) AS postRiskLevel, pr.post_id
FROM (
SELECT hf.fk_id, MIN(hf.risk_level) AS risk_level
FROM drh_post_result_hazar_factors hf
GROUP BY hf.fk_id
) hft
LEFT JOIN drh_post_result pr ON pr.id = hft.fk_id
WHERE pr.post_id IS NOT NULL
GROUP BY pr.post_id
) a
ON a.post_id = rup.post_id
LEFT JOIN drh_risk_unit ru ON ru.id = rup.risk_unit_id
WHERE ru.unit_source = '1'
) ht1
UNION ALL
SELECT ht2.*
FROM (
SELECT a.*, rup.risk_unit_id
FROM drh_risk_unit_post rup
LEFT JOIN (
SELECT MIN(hft.risk_level) AS postRiskLevel, sm.post_id
FROM (
SELECT hf.fk_id, MIN(hf.risk_level) AS risk_level
FROM drh_post_result_hazar_factors hf
GROUP BY hf.fk_id
) hft
LEFT JOIN drh_safety_matters sm ON sm.id = hft.fk_id
WHERE sm.post_id IS NOT NULL
GROUP BY sm.post_id
) a
ON a.post_id = rup.post_id
LEFT JOIN drh_risk_unit ru ON ru.id = rup.risk_unit_id
WHERE ru.unit_source = '2'
) ht2
) ull
GROUP BY ull.risk_unit_id
) tll
LEFT JOIN sys_dict_item dt ON tll.unitRiskLevel = dt.item_value
LEFT JOIN sys_dict d ON dt.dict_id = d.id
WHERE d.dict_code = 'drh_inherent_risk_level'
) c
ON c.risk_unit_id = rup.risk_unit_id
) g
WHERE g.postRiskLevelText IS NOT NULL
AND g.entid = 1
AND g.baseid = 1
ORDER BY g.create_time DESC
LIMIT 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.unitRiskLevelText
FROM drh_risk_unit_post rup
LEFT JOIN drh_risk_unit ru ON ru.id = rup.risk_unit_id
LEFT JOIN ent_post p ON p.id = rup.post_id
LEFT JOIN (
SELECT COUNT(1) AS patrolNum, pp.post_id
FROM drh_post_patrol pp
GROUP BY pp.post_id
) a
ON a.post_id = rup.post_id
LEFT JOIN (
SELECT COUNT(1) AS hiddenNum, h.post_id
FROM drh_hidden h
GROUP BY h.post_id
) ht
ON ht.post_id = rup.post_id
LEFT JOIN
(
SELECT llt.*, dt.item_text AS postRiskLevelText
FROM (
SELECT ht1.*
FROM (
SELECT a.*, rup.risk_unit_id
FROM drh_risk_unit_post rup
LEFT JOIN (
SELECT MIN(hft.risk_level) AS postRiskLevel, pr.post_id
FROM (
SELECT hf.fk_id, MIN(hf.risk_level) AS risk_level
FROM drh_post_result_hazar_factors hf
GROUP BY hf.fk_id
) hft
LEFT JOIN drh_post_result pr ON pr.id = hft.fk_id
WHERE pr.post_id IS NOT NULL
GROUP BY pr.post_id
) a
ON a.post_id = rup.post_id
LEFT JOIN drh_risk_unit ru ON ru.id = rup.risk_unit_id
WHERE ru.unit_source = '1'
) ht1
UNION ALL
SELECT ht2.*
FROM (
SELECT a.*, rup.risk_unit_id
FROM drh_risk_unit_post rup
LEFT JOIN (
SELECT MIN(hft.risk_level) AS postRiskLevel, sm.post_id
FROM (
SELECT hf.fk_id, MIN(hf.risk_level) AS risk_level
FROM drh_post_result_hazar_factors hf
GROUP BY hf.fk_id
) hft
LEFT JOIN drh_safety_matters sm ON sm.id = hft.fk_id
WHERE sm.post_id IS NOT NULL
GROUP BY sm.post_id
) a
ON a.post_id = rup.post_id
LEFT JOIN drh_risk_unit ru ON ru.id = rup.risk_unit_id
WHERE ru.unit_source = '2'
) ht2
) llt
LEFT JOIN sys_dict_item dt ON llt.postRiskLevel = dt.item_value
LEFT JOIN sys_dict d ON dt.dict_id = d.id
WHERE d.dict_code = 'drh_inherent_risk_level'
)
b
ON b.risk_unit_id = rup.risk_unit_id
AND b.post_id = rup.post_id
LEFT JOIN (
SELECT tll.*, dt.item_text AS unitRiskLevelText
FROM (
SELECT ull.risk_unit_id, MIN(ull.postRiskLevel) AS unitRiskLevel
FROM (
SELECT ht1.*
FROM (
SELECT a.*, rup.risk_unit_id
FROM drh_risk_unit_post rup
LEFT JOIN (
SELECT MIN(hft.risk_level) AS postRiskLevel, pr.post_id
FROM (
SELECT hf.fk_id, MIN(hf.risk_level) AS risk_level
FROM drh_post_result_hazar_factors hf
GROUP BY hf.fk_id
) hft
LEFT JOIN drh_post_result pr ON pr.id = hft.fk_id
WHERE pr.post_id IS NOT NULL
GROUP BY pr.post_id
) a
ON a.post_id = rup.post_id
LEFT JOIN drh_risk_unit ru ON ru.id = rup.risk_unit_id
WHERE ru.unit_source = '1'
) ht1
UNION ALL
SELECT ht2.*
FROM (
SELECT a.*, rup.risk_unit_id
FROM drh_risk_unit_post rup
LEFT JOIN (
SELECT MIN(hft.risk_level) AS postRiskLevel, sm.post_id
FROM (
SELECT hf.fk_id, MIN(hf.risk_level) AS risk_level
FROM drh_post_result_hazar_factors hf
GROUP BY hf.fk_id
) hft
LEFT JOIN drh_safety_matters sm ON sm.id = hft.fk_id
WHERE sm.post_id IS NOT NULL
GROUP BY sm.post_id
) a
ON a.post_id = rup.post_id
LEFT JOIN drh_risk_unit ru ON ru.id = rup.risk_unit_id
WHERE ru.unit_source = '2'
) ht2
) ull
GROUP BY ull.risk_unit_id
) tll
LEFT JOIN sys_dict_item dt ON tll.unitRiskLevel = dt.item_value
LEFT JOIN sys_dict d ON dt.dict_id = d.id
WHERE d.dict_code = 'drh_inherent_risk_level'
)
c
ON c.risk_unit_id = rup.risk_unit_id
WHERE
b.postRiskLevelText IS NOT NULL
and ru.entid = 1
and ru.baseid = 1
ORDER BY ru.create_time DESC
LIMIT 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