0
select round(avg(et_gsm_sınyal)) as sinyal,mahalle_kodu,ilce_kodu,sebeke 
from 
    (select et_gsm_sınyal,sozlesme_no,SUBSTR(et_operator,1,5) as sebeke 
    from thkol316old 
    where tarih >= ADD_MONTHS (TRUNC (SYSDATE, 'MM'), -1) 
    AND tarih < TRUNC(SYSDATE, 'MM')) okuma, 
    (select sozlesme_no,ilce_kodu,mahalle_kodu from commt020) bilgiler 
where okuma.sozlesme_no=bilgiler.sozlesme_no  
group by mahalle_kodu,ilce_kodu,sebeke;
  • commt020 -> 顧客テーブル
  • thkol316old -> 古い請求表

このクエリは機能しますが、動作が非常に遅くなります。

応答時間は約 550 秒です。

このクエリをより速く実行するにはどうすればよいですか?

実行計画です

SELECT STATEMENT 7547          

 HASH 
     GROUP BY    7547          

 FILTER 


 Filter Predicates 

 ADD_MONTHS(TRUNC(SYSDATE@!,'fmmm'),-1)

 NESTED LOOPS 


 NESTED LOOPS 
         7546          

 TABLE ACCESS 
 COMMT020    BY GLOBAL INDEX ROWID   3   ROW LOCATION    ROW LOCATION`
4

3 に答える 3

0

まず第一に、COMMT020 テーブルからいくつかの列を選択するためだけに BILIGILER インライン ビューは必要ありません。そのテーブルから直接選択してもまったく問題ありません。

SELECT ROUND(AVG(et_gsm_s1nyal)) AS sinyal,
      mahalle_kodu,ilce_kodu,sebeke
FROM (
    SELECT et_gsm_s1nyal,
          sozlesme_no,
          SUBSTR(et_operator,1,5) AS sebeke
    FROM thkol316old
    WHERE tarih >= ADD_MONTHS (TRUNC (SYSDATE, 'MM'), -1)
    AND   tarih < TRUNC(SYSDATE, 'MM')
    ) okuma, commt020    
WHERE okuma.sozlesme_no = commt020.sozlesme_no
GROUP BY mahalle_kodu,ilce_kodu,sebeke
/

それでは、ANSI結合式を使って結合を書き直してみましょう。古い Oracle スタイルの結合よりも ANSI 結合を好みます。これにより、結合条件をフィルタリング条件から分離できるため、実際に何が起こっているかがより明確になります。また、テーブルにエイリアスを割り当て、どのテーブルからどの列を選択するかを明確に示すのも良い方法です。

SELECT ROUND(AVG(o.et_gsm_s1nyal)) AS sinyal,
      c.mahalle_kodu, c.ilce_kodu, o.sebeke
FROM (
    SELECT th.et_gsm_s1nyal,
          th.sozlesme_no,
          SUBSTR(th.et_operator,1,5) AS sebeke
    FROM thkol316old th
    WHERE th.tarih >= ADD_MONTHS (TRUNC (SYSDATE, 'MM'), -1)
    AND   th.tarih < TRUNC(SYSDATE, 'MM')
    ) okuma o
JOIN  commt020 c ON o.sozlesme_no = c.sozlesme_no   
GROUP BY c.mahalle_kodu, c.ilce_kodu, o.sebeke
/

これで、残りのインライン ビューも冗長であることがより明確になりました。これらのテーブルの詳細を知らずに判断するのは難しいですが、インライン ビューを「アンラップ」して、直接結合に置き換えた方がよいでしょう。

SELECT ROUND(AVG(th.et_gsm_s1nyal)) AS sinyal,
       c.mahalle_kodu,
       c.ilce_kodu,
       SUBSTR(th.et_operator,1,5) AS sebeke
FROM  commt020 c
JOIN  thkol316old th ON c.sozlesme_no = th.sozlesme_no
WHERE th.tarih >= ADD_MONTHS (TRUNC (SYSDATE, 'MM'), -1)
AND   th.tarih < TRUNC(SYSDATE, 'MM')
GROUP BY c.mahalle_kodu, c.ilce_kodu, SUBSTR(th.et_operator,1,5)
/

残念ながら、このクエリをさらに最適化するには、次のような追加情報が必要です。

  • 新しい実行計画。
  • 使用している Oracle のバージョン。
  • THKOL316OLD および COMMT020 テーブルの行数。
  • それらのテーブルに存在するインデックス。
于 2013-08-25T23:42:27.173 に答える