0

次のようなカウント、平均、およびカンマ区切りのリストでいっぱいの1行のテーブルを生成する関数の一部として実行されるクエリがあります。

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" の部分をプログラムで他の式に置き換えています。vw_disp_details ビューの rating 列自体がサブクエリによってコンパイルされるため、実行に約 90 秒かかる「rating = 1」を除いて、それらはすべてかなり迅速に機能します。

(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

そのため、関数が実行されると、この余分なクエリによってすべてが劇的に遅くなるようです。

私の質問は、基本的に一連のカウントと平均であるこのようなクエリを実行するためのより良い (より効率的な) 方法はありますか?走るのに90秒。

4

3 に答える 3

1

vw_disp_details VIEW を MATERIALIZE することを選択できます。これにより、評価列の値が事前に計算されます。マテリアライズド ビューを最新の状態に保つ方法にはさまざまなオプションがあります。 vw_disp_details が常に正しいように、おそらく ON COMMIT 句を使用することをお勧めします。

公式ドキュメントを見て、それがうまくいくかどうかを確認してください。 http://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_6002.htm

于 2013-03-07T23:36:31.553 に答える
0

ほとんどのクエリを 1 つだけで実行します。代わりに:

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;

そして、おそらく、他の結果に対して何らかの結合を行うことができます。しかし、このステップだけでも役に立ちます。

于 2013-03-07T10:57:24.590 に答える
0

2 つのことを行うことでこの問題を解決できました。必要な結果のみを表示する新しいビューを作成することで、速度がわずかに向上しました。そのビューで、遅延の原因となったサブクエリの 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;
于 2013-03-11T16:20:48.853 に答える