我有一个查询,它作为一个函数的一部分运行,它产生一个完整的计数,平均值和逗号分隔列表的一行表,如下所示:
select
(select
count(*)
from vw_disp_details
where round = 2013
and rating = 1) applicants,
(select
count(*)
from vw_disp_details
where round = 2013
and rating = 1
and applied != 'yes') s_applicants,
(select
LISTAGG(discipline, ',')
WITHIN GROUP (ORDER BY discipline)
from (select discipline,
count(*) discipline_number
from vw_disp_details
where round = 2013
and rating = 1
group by discipline)) disciplines,
(select
LISTAGG(discipline_count, ',')
WITHIN GROUP (ORDER BY discipline)
from (select discipline,
count(*) discipline_count
from vw_disp_details
where round = 2013
and rating = 1
group by discipline)) disciplines_count,
(select
round(avg(util.getawardstocols(application_id,'1','AWARD_NAME')), 2)
from vw_disp_details
where round = 2013
and rating = 1) average_award_score,
(select
round(avg(age))
from vw_disp_details
where round = 2013
and rating = 1) average_age
from dual;
除了6个主要子查询外,还有23个。
返回类似这样的内容(如果是CSV):
applicants | s_applicants | disciplines | disciplines_count | average_award_score | average_age
107 | 67 | "speed,accuracy,strength" | 3 | 97 | 23
现在我以编程方式交换其他表达式的where子句的“rating = 1”部分。除了“rating = 1”之外,它们都运行得相当快,大约需要90秒才能运行,这是因为vw_disp_details视图中的rating列本身是由子查询编译的:
(SELECT score
FROM read r,
eval_criteria_lookup ecl
WHERE r.criteria_id = ecl.criteria_id
AND r.application_id = a.lgo_application_id
AND criteria_description = 'Overall Score'
AND type = 'ABC'
) reader_rank
因此,当函数运行时,这个额外的查询似乎会大大减慢一切。
我的问题是,是否有更好(更有效)的方式来运行这样的查询基本上只是一系列计数和平均值,我如何重构以优化速度,以便评级= 1查询不运行需要90秒。
答案 0 :(得分:1)
您可以选择VOLIALIZE vw_disp_details VIEW。这将预先计算评级列的值。有关保存物化视图的最新方法的各种选项,您可能希望使用ON COMMIT子句,以便vw_disp_details始终正确。
查看官方文档,看看它是否适合您。 http://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_6002.htm
答案 1 :(得分:0)
只用一个查询完成大部分查询。而不是做:
select
(select (count(*) from my_tab) as count_all,
(select avg(age) from my_tab) as avg_age,
(select avg(mypkg.get_award(application_id) from my_tab) as_avg-app_id
from dual;
只是做:
select count(*), avg(age),avg(mypkg.get_award(application_id)) from my_tab;
然后,也许你可以为其他结果做一些联合。但这一步本身应该有所帮助。
答案 2 :(得分:0)
我能够通过做两件事来解决这个问题:创建一个只显示我需要的结果的新视图,这给了我速度的边际收益,并在该视图中移动导致子查询的where子句滞后于视图的where子句,并将子查询的结果添加为视图中的列。这仍然会返回相同的结果,这是因为表中始终存在为查询查询的每一行访问的子查询的记录。
SELECT
a.application_id,
util.getstatus (a.application_id) status,
(SELECT score
FROM applicant_read ar,
eval_criteria_lookup ecl
WHERE ar.criteria_id = ecl.criteria_id
AND ar.application_id = a.application_id
AND criteria_description = 'Overall Score' //THESE TWO FIELDS
AND type = 'ABC' //ARE CRITERIA_ID = 15
) score
as.test_total test_total
FROM application a,
applicant_scores as
WHERE a.application_id = as.application_id(+);
成了
SELECT
a.application_id,
util.getstatus (a.application_id) status,
ar.score,
as.test_total test_total
FROM application a,
applicant_scores as,
applicant_read ar
WHERE a.application_id = as.application_id(+)
AND ar.application_id = a.application_id(+)
AND ar.criteria_id = 15;