问题
前几天线上数据库 IOPS 飙升,一直居高不下,最近并没有升级。遂查看数据库正在执行的 SQL 语句,发现有个查询离线设备的语句极其缓慢。
探寻原因
SELECT o.*
FROM
(
SELECT *
FROM pim_online
WHERE t2 IS NOT NULL
AND username LIKE 'd.f.%'
AND t2 + 32 * 60 * 1000 > +currentTimeMillis
AND t2 + 32 * 60 * 1000 < currentTimeMillis
) o
WHERE o.username NOT IN (
SELECT username
FROM pim_online
WHERE username LIKE 'd.f.%'
AND t1 + 32 * 60 * 1000 > currentTimeMillis
)
GROUP BY o.username;
这段 SQL 执行特慢。以我的 SQL 知识分析,原因分析如下:
- 子查询很慢
- like 操作符很慢
优化
实现相同的功能,不一定要这么实现,可以用别的方式实现,用很简单的 group by 就能完成,group by 的字段还有索引。
SELECT
DISTINCT
username,
max(t2) mt2
FROM pim_online
WHERE t2 IS NOT NULL
AND left(username, 3) = 'd.f'
AND t2 > 32 * 60 * 1000
AND t2 < 30 * 60 * 1000
AND t1 < 32 * 60 * 1000
GROUP BY username;
测试
用了 Java 生成 SQL 语句进行本地测试(排除网络延迟)。在数据量百万级别的时候,优化的 SQL 只需 80 ms 左右,原 SQL 需要 1200 ms,可谓惊人。
结论
- 子查询很慢
- like 操作符很慢
- 换种思路