Sql oracle中的查询优化

Sql oracle中的查询优化,sql,oracle,join,Sql,Oracle,Join,我需要从两列上连接的一个表和一个视图中获取结果 查看:800万条记录 表:5K记录 我查看了查询计划,发现查询将需要很长时间才能运行,实际上,我尝试运行此查询,但没有得到任何结果 请帮助我优化查询。我没有使用任何提示 SELECT coupon_upc , sum ( loyalty_a ) a , sum ( loyalty_b ) b , sum ( loyalty_c ) c , sum ( loyalty_x ) FROM ( SELECT c

我需要从两列上连接的一个表和一个视图中获取结果

查看:800万条记录 表:5K记录

我查看了查询计划,发现查询将需要很长时间才能运行,实际上,我尝试运行此查询,但没有得到任何结果

请帮助我优化查询。我没有使用任何提示

SELECT coupon_upc
     , sum ( loyalty_a ) a
     , sum ( loyalty_b ) b
     , sum ( loyalty_c ) c
     , sum ( loyalty_x )
  FROM ( SELECT ccd.coupon_upc                                        AS coupon_upc
              , ( CASE WHEN a.loyalty_cell = 'A' then 1 else 0 end )  AS loyalty_a
              , ( CASE WHEN a.loyalty_cell = 'B' then 1 else 0 end )  AS loyalty_b
              , ( CASE WHEN a.loyalty_cell = 'C1' then 1 else 0 end ) AS loyalty_c
              , ( CASE WHEN a.loyalty_cell = 'X' then 1 else 0 end )  AS loyalty_x
           FROM view1 a
              , ( select distinct coupon_upc
                                , coupon_id
                                , division
                             from table2
                            where schedule_key = 'XXX' ) ccd
          WHERE a.campaign_code = 'XXX'
            AND a.coupon_id = ccd.coupon_id
            AND a.division = ccd.division ) a
 GROUP BY coupon_upc

没有解释计划或模式/DDL,可以进行的优化数量是有限的

这里有一个替代方案,但您需要测试它,看看它是否有任何区别。(用相关子查询替换联接。)

除此之外,这种优化是:
-持久化视图
-索引
-重构数据结构

编辑

查询的另一个可能重构。。。我不知道Oracle会如何优化相关子查询的4个实例

SELECT
  coupon_upc,
  SUM((SELECT COUNT(*) FROM view1 WHERE campaign_code = 'XXX' AND loyalty_cell = 'A'  AND coupon_id = map.coupon_id AND division = map.division)) AS loyalty_a,
  SUM((SELECT COUNT(*) FROM view1 WHERE campaign_code = 'XXX' AND loyalty_cell = 'B'  AND coupon_id = map.coupon_id AND division = map.division)) AS loyalty_b,
  SUM((SELECT COUNT(*) FROM view1 WHERE campaign_code = 'XXX' AND loyalty_cell = 'C1' AND coupon_id = map.coupon_id AND division = map.division)) AS loyalty_c,
  SUM((SELECT COUNT(*) FROM view1 WHERE campaign_code = 'XXX' AND loyalty_cell = 'X'  AND coupon_id = map.coupon_id AND division = map.division)) AS loyalty_x
FROM
  (
  SELECT coupon_upc, coupon_id, division
  FROM table2 WHERE schedule_key = 'xxx'
  GROUP BY coupon_upc, coupon_id, division
  )
  AS map
GROUP BY
  coupon_upc
或者也许

SELECT
  map.coupon_upc, SUM(data.loyalty_a) AS a, SUM(data.loyalty_b) AS b, SUM(data.loyalty_c) AS c, SUM(data.loyalty_x) AS X
FROM
  (
  SELECT coupon_upc, coupon_id, division
  FROM table2 WHERE schedule_key = 'xxx'
  GROUP BY coupon_upc, coupon_id, division
  )
  AS map
INNER JOIN
  (
  SELECT
    coupon_id,
    division,
    SUM(CASE WHEN loyalty_cell = 'A'  THEN 1 ELSE 0 END) AS loyalty_a,
    SUM(CASE WHEN loyalty_cell = 'B'  THEN 1 ELSE 0 END) AS loyalty_b,
    SUM(CASE WHEN loyalty_cell = 'C1' THEN 1 ELSE 0 END) AS loyalty_c,
    SUM(CASE WHEN loyalty_cell = 'X'  THEN 1 ELSE 0 END) AS loyalty_x
  FROM
    view1
  WHERE
    campaign_code = 'XXX'
  )
  AS data
    ON  data.coupon_id = map.coupon_id
    AND data.division  = map.division
GROUP BY
  map.coupon_upc

另一种可能的重写是:

SELECT
    map.coupon_upc
  , COUNT(CASE WHEN a.loyalty_cell = 'A' THEN 1 ELSE NULL END) AS loyalty_a
  , COUNT(CASE WHEN a.loyalty_cell = 'B' THEN 1 ELSE NULL END) AS loyalty_b
  , COUNT(CASE WHEN a.loyalty_cell = 'C1' THEN 1 ELSE NULL END) AS loyalty_c
  , COUNT(CASE WHEN a.loyalty_cell = 'X' THEN 1 ELSE NULL END) AS loyalty_x
FROM
  ( SELECT coupon_upc, coupon_id, division
    FROM table2 WHERE schedule_key = 'xxx'
    GROUP BY coupon_upc, coupon_id, division
  ) AS map
  JOIN view1 a
    ON a.coupon_id = map.coupon_id
    AND a.division = map.division
WHERE
    a.campaign_code = 'xxx'  
GROUP BY
    map.coupon_upc

JOIN
WHERE
GROUP BY
子句中使用的字段上是否有索引?

提供查询和表/视图DDL语句会更容易帮助您。如果可以使用MVView而不是视图并在其上创建索引,则无权这样做!!如果没有
table2
(尤其是
view1
)定义语句,即使不是不可能,也很难提供帮助。
SELECT
    map.coupon_upc
  , COUNT(CASE WHEN a.loyalty_cell = 'A' THEN 1 ELSE NULL END) AS loyalty_a
  , COUNT(CASE WHEN a.loyalty_cell = 'B' THEN 1 ELSE NULL END) AS loyalty_b
  , COUNT(CASE WHEN a.loyalty_cell = 'C1' THEN 1 ELSE NULL END) AS loyalty_c
  , COUNT(CASE WHEN a.loyalty_cell = 'X' THEN 1 ELSE NULL END) AS loyalty_x
FROM
  ( SELECT coupon_upc, coupon_id, division
    FROM table2 WHERE schedule_key = 'xxx'
    GROUP BY coupon_upc, coupon_id, division
  ) AS map
  JOIN view1 a
    ON a.coupon_id = map.coupon_id
    AND a.division = map.division
WHERE
    a.campaign_code = 'xxx'  
GROUP BY
    map.coupon_upc