我需要优化此查询,请参阅注释行:
SELECT p.NUM_PROCESSO,
p.NUM_PROC_JUD,
p.Num_Proc_Jud_Antigo1,
p.Num_Proc_Jud_Antigo2,
p.Num_Proc_Jud_Novo,
a.assunto,
su.subassunto,
u.UNIDADE,
s.SERVIDOR,
dvj.data_vinc,
p.TIPO,
c.DESC_CLASSIF
FROM processo p
LEFT OUTER JOIN assunto a
ON a.cod_assunto = p.cod_assunto
LEFT OUTER JOIN subassunto su
ON su.cod_subassunto = p.cod_subassunto
LEFT OUTER JOIN Distrib_VincJud dvj
ON dvj.num_processo = p.num_processo
LEFT OUTER JOIN servidor s
ON S.COD_SERVIDOR = dvj.COD_SERVIDOR
LEFT OUTER JOIN unidade u
ON u.COD_UNIDADE = s.COD_UNIDADE
LEFT OUTER JOIN Classif_Processo c
ON C.COD_CLASSIF = p.COD_CLASSIF
WHERE p.TIPO = 'J'
AND p.NUM_PROCESSO NOT IN (SELECT d.num_processo
FROM distribuicao d
WHERE d.COD_SERVIDOR in ( '0', '000' )
AND d.num_distribuicao IN
(SELECT MAX(num_distribuicao)
FROM Distribuicao
GROUP BY num_processo)
--this suquery return 100k lines !!! and consume all CPU:
AND dvj.id_vinc IN
(SELECT MAX(id_vinc)
FROM Distrib_VincJud
where ativo = '1'
GROUP BY num_processo))
AND p.NUM_PROCESSO NOT IN (SELECT num_processo
FROM Anexos)
AND s.ATIVO = 1
此刻我的可怕解决方案:http://pastebin.com/C4PHNsSc
答案 0 :(得分:1)
我要做的是将IN
和NOT IN
转换为联接:
SELECT p.NUM_PROCESSO, p.NUM_PROC_JUD, p.Num_Proc_Jud_Antigo1,
p.Num_Proc_Jud_Antigo2, p.Num_Proc_Jud_Novo, a.assunto,
su.subassunto, u.UNIDADE, s.SERVIDOR, dvj.data_vinc, p.TIPO,
c.DESC_CLASSIF
FROM
processo p
INNER JOIN (
SELECT p.num_processo,
CASE WHEN dvj.id_vinc IS NOT NULL
AND d.num_distribuicao IS NOT NULL
OR a.num_processo IS NOT NULL THEN
1
ELSE
0
END exclude
FROM
processo p
LEFT JOIN Anexos a
ON p.num_processo = a.num_processo
LEFT JOIN (
SELECT num_processo,
MAX(num_distribuicao) AS max_distribuicao
FROM Distribuicao
GROUP BY num_processo
) md ON p.num_processo = md.num_processo
LEFT JOIN (
SELECT num_processo, MAX(id_vinc) AS max_vinc
FROM Distrib_VincJud
WHERE ativo = '1'
GROUP BY num_processo
) mv on p.num_processo = mv.num_processo
LEFT JOIN distribuicao d
ON p.num_processo = d.num_processo
AND md.max_distribuicao = d.num_distribuicao
LEFT JOIN Distrib_VincJud dvj
ON p.num_processo = dvj.num_processo
AND mv.max_vinc = dvj.id_vinc
WHERE d.COD_SERVIDOR in ('0', '000')
) IncExc
ON p.num_processo = IncExc.num_processo
LEFT OUTER JOIN assunto a
ON a.cod_assunto = p.cod_assunto
LEFT OUTER JOIN subassunto su
ON su.cod_subassunto = p.cod_subassunto
LEFT OUTER JOIN Distrib_VincJud dvj
ON dvj.num_processo = p.num_processo
LEFT OUTER JOIN servidor s
ON S.COD_SERVIDOR = dvj.COD_SERVIDOR
LEFT OUTER JOIN unidade u
ON u.COD_UNIDADE = s.COD_UNIDADE
LEFT OUTER JOIN Classif_Processo c
ON C.COD_CLASSIF = p.COD_CLASSIF
WHERE
p.TIPO = 'J'
AND IncExc.exclude = 0
AND s.ATIVO = 1
答案 1 :(得分:0)
这部分
AND p.NUM_PROCESSO NOT IN (
SELECT d.num_processo FROM distribuicao d
WHERE d.COD_SERVIDOR in ('0','000')
AND d.num_distribuicao IN (
SELECT MAX(num_distribuicao) FROM Distribuicao GROUP BY num_processo
)
和这部分
AND p.NUM_PROCESSO NOT IN (
SELECT num_processo FROM Anexos
)
将成为查询中最大的瓶颈,因为你已经有了嵌套的子查询。
你也有一些:
SELECT MAX(id_vinc) FROM Distrib_VincJud where ativo = '1' GROUP BY num_processo)
SELECT MAX(num_distribuicao) FROM Distribuicao GROUP BY num_processo
您可以通过让这些单独的查询存储结果来获得更多秒数。
实际上,您可能最好有一个单独的表,其中包含这些NOT IN(...)值,这些值在每次插入数据库时都会更新。这完全取决于您运行每个查询的频率。
您是否尝试在这些上运行查询优化工具?
答案 2 :(得分:0)
分离子查询,然后进行连接
即。首先查找您在一个查询中排除的所有num_processo。在num_processo字段上执行与processo表的左连接,并排除第一个表的num_processo字段为空的那些
编辑: 表distribuicao和distrib_vincJud之间的关系是什么?
这条线正在扼杀你的表现......
AND dvj.id_vinc IN
( SELECT MAX(id_vinc)
FROM Distrib_VincJud
where ativo = '1'
GROUP BY num_processo
)
子查询中的子查询,然后引用子查询之外的连接表??????