清理几年前编写的查询中的一些混乱,我注意到以下查询是导致结果变慢的原因。我试图寻找替代品但不太成功。
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
减慢了查询速度。有什么想法吗?
答案 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