对“不存在”和“存在”执行调优

时间:2018-09-21 17:45:12

标签: oracle

SELECT * 
FROM tableA RS1
INNER JOIN TableB TB
   on  TB.headkey =Rs1.headerkey
INNER JOIN TableC TC
     on  TC.headkey =Rs1.headerkey
.....
.....  {Several Inner joins on different tables}
.....
WHERE 
    "RS1"."SQTY" > 0 AND
    "RS1"."PP_KEY" = '123' AND
    TRIM(BOTH FROM "RS1"."CTOLK") IS NULL AND
    NOT ( EXISTS (
    SELECT
        1
    FROM
        "tableaA" "RS2" 
    WHERE 
        "RS2"."SQTY" > 0 AND
        "RS2"."STAT" < '33800' AND
        "RS2"."headerkey" = "RS1"."headerkey"
    ) ) AND
    EXISTS (
    SELECT
        1
    FROM
        "tableaA" "RS2" 
    WHERE 
        "RS2"."SQTY" > 0 AND
        "RS2"."STaT" = '33800.100' AND
        "RS2"."SDATE" BETWEEN TRUNC(TRUNC(CURRENT_DATE)) - 7 AND TRUNC(TRUNC(CURRENT_DATE)) AND
        "RS2"."headerkey" = "RS1"."headerkey"
    )

是否有任何有效的方式编写“ WHERE子句”,因为“ tableA”具有超过2.5亿条记录,并且在where子句中重复了两次以上,从而导致执行时间很长

1 个答案:

答案 0 :(得分:0)

为此目的引入了很多分析函数……避免必须多次读取同一张表。您需要两个条件分析计数-读取tableA时(不是全部,只有"SQTY" > 0的行,如果有区别的话),这些行按headerkey进行分区,并且计算两个所需的条件计数。然后,您可以过滤读取行(并添加分析函数),替换WHERE子句的结果。

类似这样的事情:(使用WITH子句,使代码更具可读性)

WITH
  PREP as (
    SELECT *,
           count(case when "STAT" < '33800' then 1 end) 
                                  over (partition by headerkey) as ct1,
           count(case when "STAT" = '33800.100' 
                       and "SDATE" between trunc(sysdate) - 7 and trunc(sysdate)
                      then 1 end) over (partition by headerkey) as ct2
    FROM   tableA
    where  "SQTY" > 0
  ),
  RS2 as (
    SELECT * -- or just the columns you need
    FROM   PREP
    WHERE  "PP_KEY" = '123'
      AND  TRIM(BOTH FROM "CTOLK") IS NULL
      AND  ct1 = 0
      and  ct2 > 0
  )

SELECT * 
FROM  RS1
INNER JOIN TableB TB
   on  TB.headkey =Rs1.headerkey
INNER JOIN TableC TC
     on  TC.headkey =Rs1.headerkey
.....
.....  {Several Inner joins on different tables}
.....
WHERE 
   .......