带有左连接的SQL查询速度变慢

时间:2017-02-03 02:13:08

标签: sql oracle performance reporting-services ssrs-2012

清理几年前编写的查询中的一些混乱,我注意到以下查询是导致结果变慢的原因。我试图寻找替代品但不太成功。

WITH cat
     AS (SELECT main.category_id main_id,
                main.description main_desc,
                sub1.category_id sub1_id,
                sub1.description sub1_desc,
                sub2.category_id sub2_id,
                sub2.description sub2_desc,
                sub3.category_id sub3_id,
                sub3.description sub3_desc,
                NVL (
                   NVL (NVL (sub3.category_id, sub2.category_id),
                        sub1.category_id),
                   main.category_id)
                   lowest
           FROM iod.sr_category main
                -- We need to insert a temporary null row and include it in the join so the categories which are not leaves are also included
                LEFT JOIN
                (SELECT category_id, description, parent_id
                   FROM iod.sr_category
                 UNION
                 SELECT NULL, NULL, NULL
                   FROM DUAL) sub1
                   ON (   main.category_id = sub1.parent_id
                       OR sub1.category_id IS NULL)
                LEFT JOIN
                (SELECT category_id, description, parent_id
                   FROM iod.sr_category
                 UNION
                 SELECT NULL, NULL, NULL
                   FROM DUAL) sub2
                   ON (   sub1.category_id = sub2.parent_id
                       OR sub2.category_id IS NULL)
                LEFT JOIN
                (SELECT category_id, description, parent_id
                   FROM iod.sr_category
                 UNION
                 SELECT NULL, NULL, NULL
                   FROM DUAL) sub3
                   ON (   sub2.category_id = sub3.parent_id
                       OR sub3.category_id IS NULL)
          WHERE     main.parent_id IS NULL
                AND (main.category_id IN ( :main_category))
                AND (   NVL ( :sub_category1, 0) = 0
                     OR sub1.category_id = :sub_category1)
                AND (   NVL ( :sub_category2, 0) = 0
                     OR sub2.category_id = :sub_category2)
                AND (   NVL ( :sub_category3, 0) = 0
                     OR sub3.category_id = :sub_category3))
  SELECT r.sector_report_id,
         r.created_date report_created_date --, nvl(f.sch_dep_date_local_port, f.sch_dep_date_gmt) report_search_date
                                           ,
         c.main_desc,
         c.sub1_desc,
         c.sub2_desc,
         c.sub3_desc,
         p.problem_type_code,
         p.description,
         e.first_name,
         e.last_name,
         e.employee_id,
         cl.description class,
         ROW_NUMBER ()
         OVER (PARTITION BY r.sector_report_id, cl.class_id
               ORDER BY q.question_id)
            question_num,
         q.label question,
         q.data_type,
         NVL (
            pa.answer,
            NVL (
               a.VALUE,
               NVL (a.free_text,
                    NVL (a.hours || ':' || a.minutes, 'NO ANSWER'))))
            answer,
         f.arln_code,
         f.flight_number,
         f.sch_dep_date_gmt,
         f.sch_dep_date_local_port,
         f.sch_dep_apt,
         f.sch_arv_apt,
         f.tail_number,
         f.fleet_code,
         LISTAGG (
               e_cmt.first_name
            || ' '
            || e_cmt.last_name
            || ' '
            || cmt.created_date
            || ':'
            || cmt.comment_text,
            ' ' || CHR (10))
         WITHIN GROUP (ORDER BY cmt.created_date)
            comments,
         (NVL ( (SELECT COUNT (*)
                   FROM iod.sr_photograph p
                  WHERE p.sector_report_id = r.sector_report_id),
               0))
            AS photo
    FROM iod.sr_sector_report r
         JOIN cat c ON c.lowest = r.category_id
         LEFT JOIN iod.sr_problem_type p
            ON p.problem_type_id = r.problem_type_id
         LEFT JOIN iod.ops_flight_leg f
            ON f.ops_flight_leg_id = r.ops_flight_leg_id
         LEFT JOIN iod.employee e ON e.employee_id = r.employee_id
         LEFT JOIN iod.sr_class_sector_report csr
            ON csr.sector_report_id = r.sector_report_id
         LEFT JOIN iod.sr_class cl ON cl.class_id = csr.class_id
         LEFT JOIN iod.sr_answer a ON a.sector_report_id = r.sector_report_id
         LEFT JOIN iod.sr_predefined_answer pa
            ON pa.predefined_answer_id = a.predefined_answer_id
         LEFT JOIN iod.sr_question q ON q.question_id = a.question_id
         LEFT JOIN iod.sr_comment cmt
            ON cmt.sector_report_id = r.sector_report_id
         LEFT JOIN iod.employee e_cmt ON e_cmt.employee_id = cmt.employee_id
   WHERE     (NVL ( :problem_type, 0) = 0 OR p.problem_type_id = :problem_type)
         AND TRUNC (f.sch_dep_date_local_port) BETWEEN :from_date AND :TO_DATE
         --and cast(nvl(f.sch_dep_date_local_port, f.sch_dep_date_gmt) as date) between  :from_date and :to_date
         AND (--nvl(:station_from, ' ') = ' ' or
              f.sch_dep_apt IN ( :station_from))
         AND (--nvl(:station_to, ' ') = ' ' or
              f.sch_arv_apt IN ( :station_to))
GROUP BY r.sector_report_id,
         r.created_date,
         c.main_desc,
         c.sub1_desc,
         c.sub2_desc,
         c.sub3_desc,
         p.problem_type_code,
         p.description,
         e.first_name,
         e.last_name,
         e.employee_id,
         cl.description,
         cl.class_id,
         q.label,
         q.data_type,
         q.question_id,
         NVL (
            pa.answer,
            NVL (
               a.VALUE,
               NVL (a.free_text,
                    NVL (a.hours || ':' || a.minutes, 'NO ANSWER')))),
         f.arln_code,
         f.flight_number,
         f.sch_dep_date_gmt,
         f.sch_dep_date_local_port,
         f.sch_dep_apt,
         f.sch_arv_apt,
         f.tail_number,
         f.fleet_code
ORDER BY TRUNC (f.sch_dep_date_local_port) ASC

所以部分

subx.category_id = suby.parent_id OR suby.category_id is null

减慢了查询速度。有什么想法吗?

1 个答案:

答案 0 :(得分:0)

如果没有解释计划或对正在实施的业务逻辑的理解,我们所能做的就是猜测。但这似乎是一种子查询因子可能有帮助的场景:

with sub as (
   SELECT category_id, description, parent_id FROM sr_category
   UNION
   SELECT null, null, null FROM DUAL)  
select 
     ....
from 
     ....
LEFT JOIN sub sub1
  ON (main.category_id = sub1.parent_id OR sub1.category_id is null)

  LEFT JOIN sub sub2
  ON (sub1.category_id = sub2.parent_id OR sub2.category_id is null)

  LEFT JOIN sub sub3
  ON (sub2.category_id = sub3.parent_id OR sub3.category_id is null)

  WHERE main.parent_id is null
  AND (main.category_id IN (:main_category))
  AND (nvl(:sub_category1, 0) = 0 OR sub1.category_id = :sub_category1)
  AND (nvl(:sub_category2, 0) = 0 OR sub2.category_id = :sub_category2)
  AND (nvl(:sub_category3, 0) = 0 OR sub3.category_id = :sub_category3))

Oracle SQL文档中介绍了WITH子句。 Find out more