记一次Sql执行从17分钟到3秒的优化

同事小A拿来了一段sql语句问我说为什么执行特别慢,跑一次要十多分钟。我试了一下,好家伙,最慢17分钟。语句如下:

SELECT T.*
FROM TABLE1 T
INNER JOIN VEMPLOYEE E ON E.ID = T.EID
WHERE ...;

其中TABLE1是一个数据记录表,VEMPLOYEE是一个员工表的视图,我看了一下视图定义,彻底被震惊了

CREATE OR REPLACE VIEW VEMPLOYEE AS
SELECT E.*
     FROM EMPLOYEE E
    WHERE     E.ID NOT IN
                 (53237,
                  268710,
                  51529,
                  273123,
                  267052,
                  270336,
                  273121,
                  273134,
                  273132,
                  51643,
                 --后边省略好几百行
);

小A解释说,客户要求有好多地方页面展示的时候要屏蔽一些员工,所以就直接搞了个员工视图来做统一的过滤处理。

那么,优化开始

在sql中使用IN或者NOT IN的性能是非常差的,至于具体原因,好多大佬解释的很清楚了,我就不再赘述。那么第一步,就是使用LEFT JOIN替换掉语句里边的NOT IN
首先创建一个表IGNORE_EMP_ID存储需要忽略的员工ID,只有一个ID列,修改视图创建语句如下:

CREATE OR REPLACE VIEW VEMPLOYEE AS
SELECT E.*
     FROM EMPLOYEE E
LEFT JOIN IGNORE_EMP_ID IE ON IE.ID = E.ID
    WHERE IE.ID IS NULL;

展示一下LEFT JOIN替换NOT IN的执行过程,假设EMPLOYEE表有ID为1、2、3这三个员工,需要忽略的ID有1、3这两个

表数据

执行

SELECT *
FROM EMPLOYEE E
LEFT JOIN ON IGNORE_EMP_ID IE ON IE.ID = E.ID;

时得到的数据为:

left join结果集

加上WHERE IE.ID IS NULL时就过滤掉了IGNORE_EMP_ID中的数据。

修改的方法告诉了小A,过了几分钟,我就问他改的咋样,他说正在往新建的IGNORE_EMP_ID表插数据。那好吧,我来帮忙插数据好了。
前面介绍过原来的sql里边都是一行一个数字排列的,我们把NOT IN里边的所有ID复制出来到txt文件

txt

然后保存文件为csv
另存为csv

找到刚刚保持的csv文件通过excel打开
excel

在B1单元格输入表达式

=CONCAT("INSERT INTO IGNORE_EMP_ID(ID) VALUES (", A1, ");")

然后回车拉至最后一行,复制出B列所有sql执行即可。


生成sql

你可能感兴趣的:(记一次Sql执行从17分钟到3秒的优化)