同事群里发慢sql优化记录
手痒打开一个看看,尝试下
速度提起来了
那么问题来了,你怎么保证优化过的sql结果和之前是一致的?
![](https://img.haomeiwen.com/i11630380/4bf00045a964428c.jpg)
即:你没改变他的逻辑
google告诉我 用minus ,对不起Mysql不支持
中间也想过自己搞个Java 多线程 加limit关键字 ,切段比较?感觉太笨拙了,
手里有锤子满世界都是钉子也不行啊
So
Mysql minus 替代品:
left join .... is null
先看两个表结构
![](https://img.haomeiwen.com/i11630380/6fc0e9dbcd35b389.png)
![](https://img.haomeiwen.com/i11630380/ac4c836ecce0cc21.png)
同样的表结构,
内容 前三条一致,最后一条不同
目标: 找出不同记录数
方式:
select s1.region_id ,s1.name, s2.region_id, s2.name
from sales_region s1
left join sales_region_new s2
on s1.region_id = s2.region_id
![](https://img.haomeiwen.com/i11630380/8fd5196add317623.png)
oye!
如果愉快的加个 s2.region_id is null 判断:
select s1.region_id ,s1.name, s2.region_id, s2.name
from sales_region s1
left join sales_region_new s2
on s1.region_id = s2.region_id
where s2.region_id is null
类似 minus的效果
![](https://img.haomeiwen.com/i11630380/9cfdaf62071d11da.png)
再直观一点:告诉我 s1 中有 而s2没有的 记录条数
SELECT
COUNT(*) AS s1Have_s2None_counts
FROM
sales_region s1
LEFT JOIN
sales_region_new s2 ON s1.region_id = s2.region_id
WHERE
s2.region_id IS NULL
![](https://img.haomeiwen.com/i11630380/4ed18704a0613b17.png)
好了,铺垫完毕
回到咱们面对的问题:
如何保证两条sql 返回的结果是一致的?
即 ,当你优化系统中的慢sql时候,
如何验证你修改后的sql和修改前的sql ,结果一致
即使你优化了速度,但不能把逻辑搞错了
例如:
SELECT
*
FROM
c_alarm_data_t
WHERE
create_date > '2019-03-13'
AND sensor_no != 'E11'
AND terminal_no IN (SELECT
terminal_no
FROM
v_terminal_t
WHERE
organization_no IN (SELECT DISTINCT
organization_no
FROM
v_terminal_t
WHERE
terminal_no IN (SELECT
terminal_no
FROM
f_dt_limitsgp_limits
WHERE
dt_limitsgp_id IN (SELECT
dt_limitsgp_id
FROM
f_dt_user_datalimitsgp
WHERE
userid = 'userid99998888test'))));
![](https://img.haomeiwen.com/i11630380/fe1036513c75aad1.png)
结果有260w, 耗时 8.2s , 这里只展示了100条
优化后(去掉莫名其妙的自己in 自己):
*
FROM
c_alarm_data_t
WHERE
create_date > '2019-03-13'
AND sensor_no != 'E11'
AND terminal_no IN
-- (SELECT
-- terminal_no
-- FROM
-- v_terminal_t
-- WHERE
-- organization_no IN (SELECT DISTINCT
-- organization_no
-- FROM
-- v_terminal_t
-- WHERE
-- terminal_no IN
--
(SELECT
terminal_no
FROM
f_dt_limitsgp_limits
WHERE
dt_limitsgp_id IN (SELECT
dt_limitsgp_id
FROM
f_dt_user_datalimitsgp
WHERE
userid = 'userid99998888test'));
![](https://img.haomeiwen.com/i11630380/436044312c57c404.png)
用时0.019s
速度提升431倍!!!
![](https://img.haomeiwen.com/i11630380/041054e14b9b7be3.jpeg)
sql 区别如下:
![](https://img.haomeiwen.com/i11630380/a242de3653d5eef5.png)
验证两个sql结果一致:
SELECT
COUNT(t1.alarm_id)
FROM
(SELECT
*
FROM
c_alarm_data_t
WHERE
create_date BETWEEN '2019-04-02 12:00:00' AND '2019-04-02 12:00:01'
AND sensor_no != 'E11'
AND terminal_no IN (SELECT
terminal_no
FROM
f_dt_limitsgp_limits
WHERE
dt_limitsgp_id IN (SELECT
dt_limitsgp_id
FROM
f_dt_user_datalimitsgp
WHERE
userid = 'userid99998888test'))
LIMIT 5) AS t1
LEFT JOIN
(SELECT
*
FROM
c_alarm_data_t
WHERE
create_date BETWEEN '2019-04-02 12:00:00' AND '2019-04-02 12:00:01'
AND sensor_no != 'E11'
AND terminal_no IN (SELECT
terminal_no
FROM
v_terminal_t
WHERE
organization_no IN (SELECT DISTINCT
organization_no
FROM
v_terminal_t
WHERE
terminal_no IN (SELECT
terminal_no
FROM
f_dt_limitsgp_limits
WHERE
dt_limitsgp_id IN (SELECT
dt_limitsgp_id
FROM
f_dt_user_datalimitsgp
WHERE
userid = 'userid99998888test'))))
LIMIT 5) AS t2 ON t1.alarm_id = t2.alarm_id
WHERE
t2.alarm_id IS NULL;
![](https://img.haomeiwen.com/i11630380/0f79a588dd9b4cc5.png)
为了提高速度,sql做了轻微修改,
时间段缩小为1s
limit 5 只取5条
即使这样,这个判定还要8.1s...
做个记录吧,谁有更好的方案,欢迎指教
话说 简书为何没有标签功能?
网友评论