更新查询以进行优化

时间:2019-02-07 14:00:16

标签: oracle

下面的查询可以重写吗?它需要花费很多时间来执行,并且有大量的数据抛出临时空间问题。我认为合并将改善性能。请提供建议并帮助我以更好的方式重写它

Update table1 
Set Tgt_col ='2'
where col1 in (
SELECT  ls.col1
 FROM table1 ls 
WHERE ls. Col2 ||ls. col3||ls.col22||To_Char(ls.time_col,'YYYYMMDD') IN (
  SELECT  o1. Col2||o1. col3||o1. col22||To_Char(o1. time_col,'YYYYMMDD')
  FROM table1 o1
  INNER JOIN table1 o2 ON o1. Col2 = o2. Col2
  WHERE o1. col3<> o2. col3
  AND  Nvl(o1. col22, 'XX') = Nvl(o2. col22, 'XX')
  AND To_Char(o1. time_col,'YYYYMMDD') = To_Char(o2. time_col,'YYYYMMDD')
  AND o1.date_col = :A
  AND o2. date_col = :A
  AND o1.col10 = o2.col10
  AND o1.col4 IN ('A','B','C')
  AND o1.is_root=0 AND o1.is_leaf=1
  AND o2. col4 IN ('A','B','C')
  AND o2.is_root=0 AND o2.is_leaf=1
  AND o1.col5 IN ('US','CA')
  AND o2.col5 IN ('US','CA')
GROUP BY o1. Col2||o1. col3||o1. col22||To_Char(o1. time_col,'YYYYMMDD')
)
AND ls. col4 IN ('A','B','C')
AND ls.tgt_col IS NULL
AND ls. date_col = :A
AND ls.col5 IN ('US','CA')
AND ls.ID1 IN (SELECT ID1 FROM table2 F
                                          WHERE F.col6 IN (SELECT col6  FROM table3
                                                               WHERE date_col =:A AND col7 = 1 )
                                                                                                                AND F.col8 = '1')
);

2 个答案:

答案 0 :(得分:0)

尝试以下代码,它应该更快:

UPDATE table1
   SET Tgt_col = '2'
 WHERE EXISTS (SELECT 1
                 FROM table1 ls
                 JOIN table2 F
                   ON (f.ID1 = ls.ID1)
                 JOIN table3 t3
                   ON (t3.col6 = F.col6
                       -- IF :A is always inserted, you can remove if-null checkings for this date_col
                       AND (   (t3.date_col is null AND ls.date_col is null)
                            OR t3.date_col = ls.date_col
                            )
                       )
                WHERE ls.col1 = table1.col1
                  AND EXISTS (SELECT 1
                                FROM table1 o1
                                JOIN table1 o2 
                                  ON (o1.Col2 = o2.Col2
                                      AND o1.col10 = o2.col10
                                      AND o1.is_root = o2.is_root
                                      AND o1.is_leaf = o2.is_leaf
                                      AND (   (o1.time_col is null AND o2.time_col is null)
                                           OR o1.time_col = o2.time_col
                                           )
                                      AND (   (o1.col22 is null AND o2.col22 is null)
                                           OR o1.col22 = o2.col22
                                           )
                                      -- IF :A is always inserted, you can remove if-null checkings for date_col
                                      AND (   (o1.date_col is null AND o2.date_col is null)
                                           OR o1.date_col = o2.date_col
                                           )
                                      AND o1.col3 != o2.col3)
                               WHERE     (o1.Col2 = ls.Col2 OR (o1.Col2 is null AND ls.Col2 is null))
                                     AND (o1.col3 = ls.col3 OR (o1.col3 is null AND ls.col3 is null))
                                     AND (o1.col22 = ls.col22 OR (o1.col22 is null AND ls.col22 is null))
                                     AND (o1.time_col = ls.time_col OR (o1.time_col is null AND ls.time_col is null))
                                     -- IF :A is always inserted, you can remove if-null checkings for this date_col
                                     AND (o1.date_col = ls.date_col OR (o1.date_col is null AND ls.date_col is null))
                                     AND o1.is_root = 0
                                     AND o1.is_leaf = 1
                                     -- IF o1.col4 should be equal to o2.col4 THEN also add it inside `ON` and remove one of two from here
                                     AND o1.col4 IN ('A', 'B', 'C')
                                     AND o2.col4 IN ('A', 'B', 'C')
                                     -- IF o1.col5 should be equal to o2.col5 THEN also add it inside `ON` and remove one of two from here
                                     AND o1.col5 IN ('US', 'CA')
                                     AND o2.col5 IN ('US', 'CA')
                                     AND rownum = 1)
                  -- IF ls.col4 should be equal to col4 from inside the subquery THEN add it inside as, for example, for col22
                  AND ls.col4 IN ('A', 'B', 'C')
                  AND ls.tgt_col IS NULL
                  AND ls.date_col = :A
                  -- IF ls.col5 should be equal to col5 from inside the subquery THEN add it inside as, for example, for col22
                  AND ls.col5 IN ('US', 'CA')
                  AND F.col8 = '1'
                  AND t3.col7 = 1
                  AND rownum = 1);

主要区别在于:

  • 删除连接,并在where子句中添加比较值
  • EXISTSrownum一起使用IN
  • JOININ比较中使用table2 F代替table3

如果col1是唯一键,则将所有ls table检查写入外部查询(ls.col4 IN ('A', 'B', 'C') AND ls.tgt_col IS NULL AND ls.date_col = :A AND ls.col5 IN ('US', 'CA'))中,以减少通过EXISTS检查的行数。 / p>

代码内的注释中还有更多提示。

在提交前始终检查数据更改

希望我能帮上忙!

答案 1 :(得分:0)

在没有可用于测试的数据的情况下,我认为以下内容将比您当前的查询更快:

column

似乎您正在尝试在table1中查找col1值,其中每个col2,col3,time_col,col10和col22组合都具有多个不同的col3值,因此我使用了解析计数功能来找出该值。您可能会发现EXISTS比IN更好;您可以测试a)我的查询是否有效,b)用EXISTS替换IN是否对您的数据更快。