mysql 的 sql 优化,佬们有啥建议,被监控出慢查询

2023-08-04 14:16:59 +08:00
 nice2cu
SELECT a.status, a.contract_id, a.product_id, b.num AS total , SUM(a.product_num - a.contract_outstock_num) AS sumNum FROM tableA a, tableB b
WHERE a.corpid = ? AND a.del = ? AND b.corpid = ? AND b.del = ? AND a.product_id = b.id AND a.is_produce = ? AND a.type = ?
GROUP BY a.contract_id, a.product_id
HAVING sumNum > total
ORDER BY a.id, a.product_id, a.contract_id
2272 次点击
所在节点    MySQL
24 条回复
nice2cu
2023-08-04 14:18:10 +08:00
索引该建的都建了,但由于数据量比较大,还是慢,有啥建议吗
zoharSoul
2023-08-04 14:18:35 +08:00
申请个从库在上面跑
你这慢就对了
nice2cu
2023-08-04 14:21:15 +08:00
@zoharSoul 这个如果拆成俩 sql ,在内存去计算过滤,感觉也不太好,如果其中 sql 查出的数据量比较大的话
zoharSoul
2023-08-04 14:32:08 +08:00
@nice2cu #3 所以就别拆.
申请个从库在上面跑好了
T0m008
2023-08-04 14:36:22 +08:00
可以建临时表的话,就先建一个临时表,把这个 sql 拆开,会快很多
jenlors
2023-08-04 14:54:21 +08:00
explain 贴一下,另外你这没用 join 吧
ljsh093
2023-08-04 16:18:01 +08:00
用 join ,再看下能不能把 having 去了
zjsxwc
2023-08-04 16:25:01 +08:00
拆 2 个 sql 不行吗?

1. select b.id from B where b.corpid = ? AND b.del = ?
得到 b 的 id 集合 bIdList

2. select a.x,a.y..,SUM() as sumNum from a where a.corpid = ? AND a.del = ? AND a.product_id IN (bIdList) GROUP BY a.contract_id, a.product_id
HAVING sumNum > total
ORDER BY a.id, a.product_id, a.contract_id
zjsxwc
2023-08-04 16:27:26 +08:00
@zjsxwc #6 合成一个 sql

select a.x,a.y..,SUM() as sumNum from a where a.corpid = ? AND a.del = ? AND a.product_id IN (

select b.id from B where b.corpid = ? AND b.del = ?

) GROUP BY a.contract_id, a.product_id
HAVING sumNum > total
ORDER BY a.id, a.product_id, a.contract_id
wander555
2023-08-04 16:28:21 +08:00
group by 的原因,去重最好先查出来再去
vovoim
2023-08-04 16:30:30 +08:00
上个 vespa engine ,在 vespa engine 上做统计查询
xudaxian520bsz
2023-08-04 16:50:29 +08:00
SELECT a.status, a.contract_id, a.product_id, b.num AS total, SUM(a.product_num - a.contract_outstock_num) AS sumNum
FROM tableA a
INNER JOIN tableB b ON a.product_id = b.id
WHERE a.corpid = ? AND a.del = ? AND b.corpid = ? AND b.del = ? AND a.is_produce = ? AND a.type = ?
GROUP BY a.contract_id, a.product_id
HAVING EXISTS(SELECT 1 FROM tableB WHERE id = a.product_id AND num < a.product_num - a.contract_outstock_num)
ORDER BY a.id, a.product_id, a.contract_id
nice2cu
2023-08-04 17:15:26 +08:00
@zjsxwc total 没取到
zjsxwc
2023-08-04 17:23:21 +08:00
@nice2cu 确实我漏了 total ,

还是拆 2 个 sql ,但需要加一步客户端程序自己过滤。

1. select b.id,b.num as total from B where b.corpid = ? AND b.del = ?
得到 b 的 id 集合 bIdList 与 b.id 对应的 total 数据 map 比如 totalByBId = {
<bId> : total
}

2. select a.x,a.y..,SUM() as sumNum from a where a.corpid = ? AND a.del = ? AND a.product_id IN (bIdList) GROUP BY a.contract_id, a.product_id
ORDER BY a.id, a.product_id, a.contract_id

对 2 的结果通过 totalByBId 过滤出满足的结果。
nice2cu
2023-08-04 17:26:56 +08:00
@xudaxian520bsz num < a.product_num - a.contract_outstock_num 这个条件 sumNum > total 是不是意思不一样了
nice2cu
2023-08-04 17:30:39 +08:00
@zjsxwc 可能第一个查询的数据会很多 加到内存算感觉会是个隐患
xuanbg
2023-08-05 08:59:56 +08:00
数据量大是没办法优化的。。。
wengyanbin
2023-08-05 11:33:19 +08:00
select t.*,b.num from (select a.status, a.contract_id, a.product_id, sum() from table a where a.corpid = ? AND a.del = ? group by a.contract_id, a.product_id) as t,table b where t.product_id=b.id and t.sumNum>b.num
zjsxwc
2023-08-05 12:39:43 +08:00
@nice2cu 不知道用 left join 会不会好一点,起码不会和你最开始直接 from 两个表搞笛卡尔积的性能那么差。



SELECT a.status, a.contract_id, a.product_id, total , SUM(a.product_num - a.contract_outstock_num) AS sumNum

FROM tableA a
LEFT JOIN ( select B.id as bid, B.num as total from B where B.corpid = ? AND B.del = ? ) tb
ON tb.bid=a.product_id

WHERE a.corpid = ? AND a.del = ? AND a.is_produce = ? AND a.type = ?

GROUP BY a.contract_id, a.product_id
HAVING sumNum > total
ORDER BY a.id, a.product_id, a.contract_id
xchaoinfo
2023-08-06 15:56:49 +08:00
同意 @zjsxwc 的思路,改成子查询 然后 id 去重,速度应该提高很多

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/962391

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX